Linux网络-使用Tcp协议进行网络通信并通过网络接口实现远端翻译

本文主要是介绍Linux网络-使用Tcp协议进行网络通信并通过网络接口实现远端翻译,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • Tcp协议
  • Tcp协议常见API接口
    • 1. int socket(int domain, int type, int protocol);
    • 2. int bind(int socket, const struct sockaddr *address, socklen_t address_len);
      • struct sockaddr
    • 3. int listen(int socket, int backlog);
    • 4. int accept(int socket, struct sockaddr *restrict address,socklen_t *restrict address_len);
    • 5.int connect(int socket, const struct sockaddr *address,socklen_t address_len);
  • telnet通信
  • 服务器代码
    • 1. 单进程版本
    • 2.多进程版本
    • 3.多线程版本
    • 4. 线程池版本(附加字典功能)
      • Main.cc
      • TcpServer.cpp
      • ThreadPool.hpp
      • Task.hpp
      • log.hpp
      • dictionary.hpp
      • dictionary.txt 字典文本(简易)
  • 客户端代码
  • 翻译效果图

Tcp协议

简单了解一下Tcp协议,他与Udp协议都是传输层协议,而他与Udp协议的区别就是Tcp是有连接、可靠传输并且是面向字节流的一种协议。

Tcp协议常见API接口

前两个接口与Udp协议用法一样,只不过将申请套接字的SOCK_DGRAM改为了面向字节流的SOCK_STREAM。

1. int socket(int domain, int type, int protocol);

创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)

参数 int domin :指定要在其中创建套接字的通信域。这里我们使用AF_INET采用IPV4通信域。

参数 int type : 指定要创建的套接字类型。 Tcp协议是采用面向字节流,所以是用SOCK_STREAM。

参数 int protocol :指定与套接字一起使用的特定协议。

返回值: 如果成功则返回创建的socket 文件描述符, 失败则返回-1.

代码示例

		int socket_fd = socket(AF_INET, SOCK_STREAM, 0);if (socket_fd == -1){exit(1);}

2. int bind(int socket, const struct sockaddr *address, socklen_t address_len);

绑定端口号 (TCP/UDP, 服务器)
参数 int socket 就是使用socket接口函数所创建的那个socket文件描述符。

struct sockaddr

在这里插入图片描述
由于底层有不同的网络协议,所以它们的地址格式并不相同,所以通常使用struct sockaddr* 作为参数,然后根据前16位地址类型来确定协议内容。

参数 socklen_t address_len, 结构体sockaddr的长度。
typedef unsigned int socklen_t

返回值: 如果绑定成功则返回0, 失败则返回-1.

代码示例

		int socket_fd = socket(AF_INET, SOCK_STREAN, 0);if (socket_fd == -1){exit(1);}struct sockaddr_in Server;bzero(&Server, 0);Server.sin_family = AF_INET;Server.sin_addr.s_addr = inet_addr(_ip.c_str()); //?Server.sin_port = htons(_port); //?int n = bind( socket_fd, (const struct sockaddr *)&Server, sizeof(Server));if (n != 0){exit(2);}

3. int listen(int socket, int backlog);

作用:将参数socket套接字用于监听,使其处于listen状态。
参数 backlog 这里暂时不讲,将其设为10左右即可。
返回值:成功则为0,失败则为-1。

代码示例

		int sock = socket(AF_INET, SOCK_STREAM, 0);if (sock == -1){logMessage(FATAL, "socket create failed...");exit(1);}logMessage(DEBUG, "socket create succeess...");_listensock = sock;// bind套接字struct sockaddr_in local;memset(&local, 0, sizeof local);local.sin_family = AF_INET;inet_aton(_server_ip.c_str(), &local.sin_addr);local.sin_port = htons(_server_port);if (bind(_listensock, (const sockaddr *)&local, (socklen_t)sizeof(local)) == -1){logMessage(FATAL, "bind failed..., error:%s", strerror(errno));exit(2);}logMessage(DEBUG, "bind succeess...");// listen beginif (listen(_listensock, backlog) < 0){logMessage(FATAL, "listen failed...");exit(3);}

4. int accept(int socket, struct sockaddr *restrict address,socklen_t *restrict address_len);

作用:处于listen状态的网络套接字将持续监听是否有其他网络套接字对本套接字进行链接,该接口函数会阻塞,直到有套接字进行链接,链接成功后将返回一个文件描述符

参数socket:处于listen状态的网络套接字。

参数struct sockaddr *restrict address: 输出型函数,用于保存远端主机的套接字信息。

参数socklen_t *restrict address_len: 输出型参数,用于保存远端主机的套接字的长度。

返回值:成功链接返回一个文件描述符,可对它进行读写操作,失败则返回-1。

5.int connect(int socket, const struct sockaddr *address,socklen_t address_len);

对目标网络套接字发送连接请求,一般适用于客户端去连接服务器。
参数 socket: 本地申请的套接字。
参数const struct sockaddr *address:目标网络套接字的struct sockaddr。
参数socklen_t address_len: 目标网络套接字的struct sockaddr的长度。


telnet通信

telnet是linux中可安装的程序,它是一种基于Tcp协议通信的程序,我们可以使用它来对我们的服务器进行测试。

终端输入该命令

telnet ip[xxx.xxx.xxx.xxx] port[1024+]

如果出现找不到该命令,则是因为你的linux主机没有安装telnet

输入
sudo yum install telnet
安装telnet


使用示例
telnet 127.0.0.1 8888

服务器代码

1. 单进程版本

// version 1 单进程单线程版
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <string>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include "log.hpp"
#include <netinet/in.h>
#include <string.h>const std::string default_ip = "0.0.0.0";
const uint16_t default_port = 8888;
const int backlog = 10;std::string messageHandle(const std::string &ip, uint16_t port, const std::string &message)
{time_t now = time(nullptr);struct tm *lt = localtime(&now);std::cout << lt->tm_hour << ":" << lt->tm_min << "[" << ip << ":" << port << "]: "<< message << std::endl;return message;
}
class TcpServer
{
public:TcpServer(uint16_t port = default_port, std::string ip = default_ip): _listensock(-1), _server_ip(ip), _server_port(port){}void Init(){// 申请套接字int sock = socket(AF_INET, SOCK_STREAM, 0);if (sock == -1){logMessage(FATAL, "socket create failed...");exit(1);}logMessage(DEBUG, "socket create succeess...");_listensock = sock;// bind套接字struct sockaddr_in local;memset(&local, 0, sizeof local);local.sin_family = AF_INET;inet_aton(_server_ip.c_str(), &local.sin_addr);local.sin_port = htons(_server_port);if (bind(_listensock, (const sockaddr *)&local, (socklen_t)sizeof(local)) == -1){logMessage(FATAL, "bind failed..., error:%s", strerror(errno));exit(2);}logMessage(DEBUG, "bind succeess...");// listen beginif (listen(_listensock, backlog) < 0){logMessage(FATAL, "listen failed...");exit(3);}logMessage(DEBUG, "listen succeess...");}void run(){struct sockaddr_in client;socklen_t len;while (true){memset(&client, 0, sizeof client);int socketfd = accept(_listensock, (struct sockaddr *)&client, &len);if (socketfd < 0){logMessage(WARNING, "accept failed...");continue;}logMessage(DEBUG, "accept success..., and get a link, socketfd: %d", socketfd);service(socketfd, client);}}void service(const int socketfd, const struct sockaddr_in client){uint16_t client_port = ntohs(client.sin_port);char ip_buffer[32];inet_ntop(AF_INET, (const void *)&client.sin_addr, ip_buffer, sizeof client);std::string cilent_ip = ip_buffer;// 开始接收消息char buffer[1024];while (true){memset(buffer, 0, sizeof buffer);int n = read(socketfd, buffer, sizeof buffer - 1);if (n == 0){logMessage(WARNING, "socketfd[%d] closed...", socketfd);break;}else if (n < 0){logMessage(WARNING, "read erro, socketfd[%d]...");break;}if (buffer[n - 1] == '\n'){// 使用telnet通信//std::cout << "发现\\n" << std::endl;buffer[n - 2] = 0;}else{// 使用客户端通信buffer[n] = 0;}std::string info = messageHandle(cilent_ip, client_port, buffer);write(socketfd, info.c_str(), info.size());}close(socketfd);logMessage(DEBUG, "socketfd: %d closed...", socketfd);}private:int _listensock;std::string _server_ip;uint16_t _server_port;
};

该版本缺陷很明显,没办法同时处理多个客户端的数据请求。


2.多进程版本

// version 2 多进程版
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <string>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include "log.hpp"
#include <netinet/in.h>
#include <string.h>
#include <wait.h>
const std::string default_ip = "0.0.0.0";
const uint16_t default_port = 8888;
const int backlog = 10;std::string messageHandle(const std::string &ip, uint16_t port, const std::string &message)
{time_t now = time(nullptr);struct tm *lt = localtime(&now);std::cout << lt->tm_hour << ":" << lt->tm_min << "[" << ip << ":" << port << "]: "<< message << std::endl;return message;
}
class TcpServer
{
public:TcpServer(uint16_t port = default_port, std::string ip = default_ip): _listensock(-1), _server_ip(ip), _server_port(port){}void Init(){// 申请套接字int sock = socket(AF_INET, SOCK_STREAM, 0);if (sock == -1){logMessage(FATAL, "socket create failed...");exit(1);}logMessage(DEBUG, "socket create succeess...");_listensock = sock;// bind套接字struct sockaddr_in local;memset(&local, 0, sizeof local);local.sin_family = AF_INET;inet_aton(_server_ip.c_str(), &local.sin_addr);local.sin_port = htons(_server_port);if (bind(_listensock, (const sockaddr *)&local, (socklen_t)sizeof(local)) == -1){logMessage(FATAL, "bind failed..., error:%s", strerror(errno));exit(2);}logMessage(DEBUG, "bind succeess...");// listen beginif (listen(_listensock, backlog) < 0){logMessage(FATAL, "listen failed...");exit(3);}logMessage(DEBUG, "listen succeess...");}void run(){struct sockaddr_in client;socklen_t len;while (true){memset(&client, 0, sizeof client);int socketfd = accept(_listensock, (struct sockaddr *)&client, &len);if (socketfd < 0){logMessage(WARNING, "accept failed...");continue;}logMessage(DEBUG, "accept success..., and get a link, socketfd: %d", socketfd);int pid = fork();if (pid == 0){if (fork()){// 子进程退出 这样我们的父进程就不需要等service函数执行完才waitpidexit(0);}// 孙子进程close(_listensock);service(socketfd, client);exit(0);}// 父进程close(socketfd);waitpid(pid, nullptr, 0);}}void service(const int socketfd, const struct sockaddr_in client){uint16_t client_port = ntohs(client.sin_port);char ip_buffer[32];inet_ntop(AF_INET, (const void *)&client.sin_addr, ip_buffer, sizeof client);std::string cilent_ip = ip_buffer;// 开始接收消息char buffer[1024];while (true){memset(buffer, 0, sizeof buffer);int n = read(socketfd, buffer, sizeof buffer - 1);if (n == 0){logMessage(WARNING, "socketfd[%d] closed...", socketfd);break;}else if (n < 0){logMessage(WARNING, "read erro, socketfd[%d]...");break;}if (buffer[n - 1] == '\n'){// 使用telnet通信// std::cout << "发现\\n" << std::endl;buffer[n - 2] = 0;}else{// 使用客户端通信buffer[n] = 0;}std::string info = messageHandle(cilent_ip, client_port, buffer);write(socketfd, info.c_str(), info.size());}close(socketfd);logMessage(DEBUG, "socketfd: %d closed...", socketfd);}private:int _listensock;std::string _server_ip;uint16_t _server_port;
};

缺陷是多进程需要维护的系统资源较多,连接的客户端稍微多点就不行了,简而言之就是多进程占用太大。


3.多线程版本

// version 3 多线程版
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <string>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include "log.hpp"
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>const std::string default_ip = "0.0.0.0";
const uint16_t default_port = 8888;
const int backlog = 10;std::string messageHandle(const std::string &ip, uint16_t port, const std::string &message)
{time_t now = time(nullptr);struct tm *lt = localtime(&now);std::cout << lt->tm_hour << ":" << lt->tm_min << "[" << ip << ":" << port << "]: "<< message << std::endl;return message;
}
class TcpServer;class ThreadData
{
public:ThreadData(int fd, struct sockaddr_in client): _socketfd(fd), _client(client){}int _socketfd;struct sockaddr_in _client;
};
class TcpServer
{
public:TcpServer(uint16_t port = default_port, std::string ip = default_ip): _listensock(-1), _server_ip(ip), _server_port(port){}void Init(){// 申请套接字int sock = socket(AF_INET, SOCK_STREAM, 0);if (sock == -1){logMessage(FATAL, "socket create failed...");exit(1);}logMessage(DEBUG, "socket create succeess...");_listensock = sock;// bind套接字struct sockaddr_in local;memset(&local, 0, sizeof local);local.sin_family = AF_INET;inet_aton(_server_ip.c_str(), &local.sin_addr);local.sin_port = htons(_server_port);if (bind(_listensock, (const sockaddr *)&local, (socklen_t)sizeof(local)) == -1){logMessage(FATAL, "bind failed..., error:%s", strerror(errno));exit(2);}logMessage(DEBUG, "bind succeess...");// listen beginif (listen(_listensock, backlog) < 0){logMessage(FATAL, "listen failed...");exit(3);}logMessage(DEBUG, "listen succeess...");}void run(){struct sockaddr_in client;socklen_t len;while (true){memset(&client, 0, sizeof client);int socketfd = accept(_listensock, (struct sockaddr *)&client, &len);if (socketfd < 0){logMessage(WARNING, "accept failed...");continue;}logMessage(DEBUG, "accept success..., and get a link, socketfd: %d", socketfd);ThreadData *td = new ThreadData(socketfd, client);pthread_t tid;pthread_create(&tid, nullptr, service, (void *)td);}}static void *service(void *args){pthread_detach(pthread_self());ThreadData *td = static_cast<ThreadData *>(args);uint16_t client_port = ntohs(td->_client.sin_port);char ip_buffer[32];inet_ntop(AF_INET, (const void *)&(td->_client.sin_addr), ip_buffer, sizeof(td->_client));std::string cilent_ip = ip_buffer;// 开始接收消息char buffer[1024];while (true){memset(buffer, 0, sizeof buffer);int n = read(td->_socketfd, buffer, sizeof buffer - 1);if (n == 0){logMessage(WARNING, "socketfd[%d] closed...", td->_socketfd);break;}else if (n < 0){logMessage(WARNING, "read erro, socketfd[%d]...");break;}if (buffer[n - 1] == '\n'){// 使用telnet通信// std::cout << "发现\\n" << std::endl;buffer[n - 2] = 0;}else{// 使用客户端通信buffer[n] = 0;}std::string info = messageHandle(cilent_ip, client_port, buffer);write(td->_socketfd, info.c_str(), info.size());}delete td;return nullptr;}private:int _listensock;std::string _server_ip;uint16_t _server_port;
};

相对多进程版本,系统资源维护成本没那么大,也算一种不错的方案。


4. 线程池版本(附加字典功能)

Main.cc

#include <iostream>
#include "TcpServer.hpp"
#include "threadPool.hpp"
#include "Task.hpp"
void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " port[8888-9000]\n"<< std::endl;
}//多线程版Mainint main(int argc, char* argv[]){if(argc != 2){Usage("./TcpServer");return 1;}int port = atoi(argv[1]);TcpServer ts(port);ts.Init();ts.run();return 0;}

TcpServer.cpp

                 //TcpServer.cpp
// version 4 线程池版
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <string>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include "log.hpp"
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include "threadPool.hpp"
#include "Task.hpp"const std::string default_ip = "0.0.0.0";
const uint16_t default_port = 8888;
const int backlog = 10;std::string messageHandle(const std::string &ip, uint16_t port, const std::string &message)
{time_t now = time(nullptr);struct tm *lt = localtime(&now);std::cout << lt->tm_hour << ":" << lt->tm_min << "[" << ip << ":" << port << "]: "<< message << std::endl;return message;
}
class TcpServer;class TcpServer
{
public:TcpServer(uint16_t port = default_port, std::string ip = default_ip): _listensock(-1), _server_ip(ip), _server_port(port){}void Init(){// 申请套接字int sock = socket(AF_INET, SOCK_STREAM, 0);if (sock == -1){logMessage(FATAL, "socket create failed...");exit(1);}logMessage(DEBUG, "socket create succeess...");_listensock = sock;// bind套接字struct sockaddr_in local;memset(&local, 0, sizeof local);local.sin_family = AF_INET;inet_aton(_server_ip.c_str(), &local.sin_addr);local.sin_port = htons(_server_port);if (bind(_listensock, (const sockaddr *)&local, (socklen_t)sizeof(local)) == -1){logMessage(FATAL, "bind failed..., error:%s", strerror(errno));exit(2);}logMessage(DEBUG, "bind succeess...");// listen beginif (listen(_listensock, backlog) < 0){logMessage(FATAL, "listen failed...");exit(3);}logMessage(DEBUG, "listen succeess...");}void run(){struct sockaddr_in client;socklen_t len;ThreadPool<Task>::GetInstance()->Start();while (true){memset(&client, 0, sizeof client);int socketfd = accept(_listensock, (struct sockaddr *)&client, &len);if (socketfd < 0){logMessage(WARNING, "accept failed...");continue;}logMessage(NORMAL, "accept success..., and get a link, socketfd: %d", socketfd);ThreadPool<Task> *threadpool = ThreadPool<Task>::GetInstance();threadpool->Push(Task(socketfd, client));}}private:int _listensock;std::string _server_ip;uint16_t _server_port;
};

ThreadPool.hpp

#pragma once#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <pthread.h>
#include <unistd.h>struct ThreadInfo
{pthread_t tid;std::string name;
};static const int defalutnum = 10;template <class T>
class ThreadPool
{
public:void Lock(){pthread_mutex_lock(&mutex_);}void Unlock(){pthread_mutex_unlock(&mutex_);}void Wakeup(){pthread_cond_signal(&cond_);}void ThreadSleep(){pthread_cond_wait(&cond_, &mutex_);}bool IsQueueEmpty(){return tasks_.empty();}std::string GetThreadName(pthread_t tid){for (const auto &ti : threads_){if (ti.tid == tid)return ti.name;}return "None";}public:static void *HandlerTask(void *args){ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);std::string name = tp->GetThreadName(pthread_self());while (true){tp->Lock();while (tp->IsQueueEmpty()){tp->ThreadSleep();}T t = tp->Pop();tp->Unlock();t();}}void Start(){int num = threads_.size();for (int i = 0; i < num; i++){threads_[i].name = "thread-" + std::to_string(i + 1);pthread_create(&(threads_[i].tid), nullptr, HandlerTask, this);}}T Pop(){T t = tasks_.front();tasks_.pop();return t;}void Push(const T &t){Lock();tasks_.push(t);Wakeup();Unlock();}static ThreadPool<T> *GetInstance(){if (nullptr == tp_) // ???{pthread_mutex_lock(&lock_);if (nullptr == tp_){// std::cout << "log: singleton create done first!" << std::endl;tp_ = new ThreadPool<T>();}pthread_mutex_unlock(&lock_);}return tp_;}private:ThreadPool(int num = defalutnum) : threads_(num){pthread_mutex_init(&mutex_, nullptr);pthread_cond_init(&cond_, nullptr);}~ThreadPool(){pthread_mutex_destroy(&mutex_);pthread_cond_destroy(&cond_);}ThreadPool(const ThreadPool<T> &) = delete;const ThreadPool<T> &operator=(const ThreadPool<T> &) = delete; // a=b=c
private:std::vector<ThreadInfo> threads_;std::queue<T> tasks_;pthread_mutex_t mutex_;pthread_cond_t cond_;static ThreadPool<T> *tp_;static pthread_mutex_t lock_;
};template <class T>
ThreadPool<T> *ThreadPool<T>::tp_ = nullptr;template <class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;

Task.hpp

#pragma once
#include <functional>
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include "dictionary.hpp"Dictionary dictionary;
class Task
{
public:Task(){}Task(int socketfd, const struct sockaddr_in client): _socketfd(socketfd), _client(client){}void operator()(){char key_word[64];while (true){memset(key_word, 0, sizeof key_word);int n = read(_socketfd, key_word, sizeof key_word - 1);if (n == 0){logMessage(NORMAL, "Connection closed by foreign host, socketfd[%d] closed...", _socketfd);break;}else if (n < 0){logMessage(WARNING, "read erro, socketfd[%d]...");break;}if (key_word[n - 1] == '\n'){// 使用telnet通信logMessage(DEBUG, "find \\n, telnet connection...");key_word[n - 2] = 0;}else{// 使用客户端通信key_word[n] = 0;}std::string value_word = dictionary.translate(key_word);write(_socketfd, value_word.c_str(), value_word.size());}close(_socketfd);logMessage(DEBUG, "socketfd[%d] closed...", _socketfd);}private:int _socketfd;struct sockaddr_in _client;
};

log.hpp

#pragma once
#include <iostream>
#include <stdarg.h>
#include <string>
#include <time.h>
const char *levels[] = {"NORMAL","WARNING","ERROR","FATAL","DEBUG"};#define NORMAL 0
#define WARNING 1
#define ERROR 2
#define FATAL 3
#define DEBUG 4void logMessage(int level, const char *format, ...)
{
#ifndef debugif (level == DEBUG){return;}
#endifchar stdBuffer[1024];time_t now = time(nullptr);struct tm *lt = localtime(&now);snprintf(stdBuffer, sizeof stdBuffer, "[%s][%d:%d]: ", levels[level], lt->tm_hour, lt->tm_min);char logBuffer[1024];va_list va;va_start(va, format);vsnprintf(logBuffer, sizeof logBuffer, format, va);printf("%s%s\n", stdBuffer, logBuffer);
}

dictionary.hpp

#pragma once
#include <unordered_map>
#include <string>
#include <iostream>
#include <fstream>const char separator = ':';class Dictionary
{
public:Dictionary(){Init();}bool split(const std::string &dword, std::string &part1, std::string &part2){int pos = dword.find(separator, 0);if (pos == std::string::npos){return false;}part1 = dword.substr(0, pos);part2 = dword.substr(pos + 1);}void Init(){std::ifstream in("dictionary.txt");std::string dword;while (std::getline(in, dword)){std::string part1;std::string part2;if (split(dword, part1, part2))_dic[part1] = part2;}in.close();}std::string translate(std::string key){auto it = _dic.find(key);if (it == _dic.end()){return "word unknow";}return it->second;}private:std::unordered_map<std::string, std::string> _dic;
};

dictionary.txt 字典文本(简易)

apple:苹果...
banana:香蕉...
red:红色...
yellow:黄色...
the: 这
be: 是
to: 朝向//对
and: 和
I: 我
in:...里
that: 那个
have: 有
will:for: 为了
but: 但是
as:...一样
what: 什么
so: 因此
he: 他
her: 她
his: 他的
they: 他们
we: 我们
their: 他们的
his: 它的
with:...一起
she: 她
he: 他
it:

客户端代码

客户端代码仅此一套 且可适配服务器四个版本

#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <string>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include "log.hpp"
#include <netinet/in.h>
#include <string.h>
// telnet server_ip server_port
void Usage(const std::string &proc)
{std::cout << "\n\rUsage: " << proc << " ip[xxx.xxx.xxx.xxx] port[8888-9000]\n"<< std::endl;
}int main(int argc, char *argv[])
{if (argc != 3){Usage("./TcpClient");exit(1);}// 申请socketint socketfd = socket(AF_INET, SOCK_STREAM, 0);if (socketfd < 0){logMessage(FATAL, "socket create failed...");exit(2);}// 初始化结构体sockaddrstruct sockaddr_in server;memset(&server, 0, sizeof server);server.sin_family = AF_INET;server.sin_port = htons(atoi(argv[2]));server.sin_addr.s_addr = inet_addr(argv[1]);if (connect(socketfd, (const sockaddr *)&server, sizeof server) < 0){// connect失败logMessage(FATAL, "connect create failed...");exit(3);}// connect 成功logMessage(DEBUG, "connect create seccess...");// 开始发送和读取数据std::string out_buffer;char in_buffer[1024];while (true){memset(in_buffer, 0, sizeof in_buffer);std::cout << "Send a Message@ ";std::getline(std::cin, out_buffer);write(socketfd, out_buffer.c_str(), out_buffer.size());int n = read(socketfd, in_buffer, sizeof in_buffer - 1);if (n > 0){in_buffer[n] = 0;std::cout << "Server echo Message: " << in_buffer << std::endl;}else if (n == 0){logMessage(WARNING, "Connection closed by foreign host, socketfd[%d] closed...", socketfd);break;}else if (n < 0){logMessage(WARNING, "read erro, socketfd[%d]...");break;}}close(socketfd);return 0;
}

翻译效果图

在这里插入图片描述


这篇关于Linux网络-使用Tcp协议进行网络通信并通过网络接口实现远端翻译的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1020263

相关文章

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

Linux如何查看文件权限的命令

《Linux如何查看文件权限的命令》Linux中使用ls-R命令递归查看指定目录及子目录下所有文件和文件夹的权限信息,以列表形式展示权限位、所有者、组等详细内容... 目录linux China编程查看文件权限命令输出结果示例这里是查看tomcat文件夹总结Linux 查看文件权限命令ls -l 文件或文件夹

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件