当前位置: 首页 > news >正文

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;
}

翻译效果图

在这里插入图片描述


相关文章:

  • 【React】封装一个好用方便的消息框(Hooks Bootstrap 实践)
  • oracle创建新用户,并且只给新用户赋予查询权限
  • 2024Dragon Knight CTF复现web
  • 11.1 排序算法
  • C++中的智能指针类别
  • 汽车MCU虚拟化--对中断虚拟化的思考(1)
  • 利用GNSS IMU集成提高车道级定位精度
  • Blueprints - Collision Presets相关
  • 4月啤酒品类线上销售数据分析
  • Java-集合基础
  • LeetCode # 1070. 产品销售分析 III
  • Python列表
  • RustDesk服务器
  • 整理GTX收发器示例工程(高速收发器十一)
  • 医院该如何应对网络安全?
  • 2017-08-04 前端日报
  • Android优雅地处理按钮重复点击
  • Angular6错误 Service: No provider for Renderer2
  • egg(89)--egg之redis的发布和订阅
  • HashMap剖析之内部结构
  • Spring Cloud Feign的两种使用姿势
  • tensorflow学习笔记3——MNIST应用篇
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 微信小程序设置上一页数据
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ‌Excel VBA进行间比法设计
  • #DBA杂记1
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #QT(TCP网络编程-服务端)
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • #预处理和函数的对比以及条件编译
  • (09)Hive——CTE 公共表达式
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (苍穹外卖)day03菜品管理
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (一) 初入MySQL 【认识和部署】
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • *算法训练(leetcode)第四十七天 | 并查集理论基础、107. 寻找存在的路径
  • .config、Kconfig、***_defconfig之间的关系和工作原理
  • .mp4格式的视频为何不能通过video标签在chrome浏览器中播放?
  • .net 7 上传文件踩坑
  • .Net Core 笔试1
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .NET Micro Framework初体验(二)
  • .net6 webapi log4net完整配置使用流程
  • .net开发引用程序集提示没有强名称的解决办法
  • :not(:first-child)和:not(:last-child)的用法
  • :O)修改linux硬件时间
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • []FET-430SIM508 研究日志 11.3.31
  • [120_移动开发Android]008_android开发之Pull操作xml文件