这是一个用AI生成的简单的tcp服务器代码,我稍微改动了一下命名啥的。
可以看到代码非常简短,不过却没什么问题,人工智能还是很强的。
#include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <cstring> #include <unistd.h> #define MAXLNE 4096 int main() { int listenfd, connfd; struct sockaddr_in servaddr{}; char buffer[MAXLNE]{}; // 创建套接字 listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd == -1) { std::cerr << "Failed to create socket." << std::endl; return -1; } // 设置服务器地址 servaddr.sin_family = AF_INET; servaddr.sin_port = htons(8080); // 指定端口号(这里使用8080) servaddr.sin_addr.s_addr = INADDR_ANY; // 绑定套接字到指定地址和端口 if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { std::cerr << "Failed to bind socket." << std::endl; return -1; } // 监听连接请求 if (listen(listenfd, 5) < 0) { // 允许同时处理最多5个连接请求 std::cerr << "Error in listening." << std::endl; return -1; } std::cout << "Server started. Listening for incoming connections..." << std::endl; while (true) { struct sockaddr_in client; socklen_t len = sizeof(client); // 接受连接请求 connfd = accept(listenfd, (struct sockaddr *)&client, &len); if (connfd < 0) { std::cerr << "Error in accepting connection." << std::endl; return -1; } // 读取客户端发来的数据 bzero(buffer, sizeof(buffer)); if (read(connfd, buffer, sizeof(buffer)) < 0) { std::cerr << "Error in reading data." << std::endl; return -1; } // 输出客户端发送的消息 std::cout << "Client message: " << buffer << std::endl; // 发送响应给客户端 const char *response = "Hello from server!"; if (write(connfd, response, strlen(response)) < 0) { std::cerr << "Error in sending response." << std::endl; return -1; } // 关闭连接套接字 close(connfd); } // 关闭服务器套接字 close(listenfd); return 0; }
如果我们运行这个代码,会发现它只能和client完成单次的连接和发送消息,消息发送完就会断开连接并等待client再次连接。同时,这个服务器采用的是一种基于阻塞式I/O的方式,如果有一个客户端连接上并没有关闭连接,后续连接上服务器的客户端会被阻塞在accept上,无法获得服务器的响应,直到前面的客户端关闭连接。
如果我想得到一个可以多客户端同时连接,且可以保持连接循环发消息的服务器代码的话,就可以使用多线程方式。
首先在main前写一个多线程处理客户端的函数handle_client:
void *handle_client(void *arg)
{ int connfd = *(int *)arg; char buffer[MAXLNE]{}; while(1) { // 读取客户端发来的数据 bzero(buffer, sizeof(buffer)); if (read(connfd, buffer, sizeof(buffer)) < 0) { std::cerr << "Error in reading data." << std::endl; close(connfd); return NULL; } // 输出客户端发送的消息 std::cout << "Client message: " << buffer << std::endl; // 发送响应给客户端 const char *response = "Hello from server!"; if (write(connfd, response, strlen(response)) < 0) { std::cerr << "Error in sending response." << std::endl; } } }
然后改一下while循环多线程调起
while (1)
{ struct sockaddr_in client; socklen_t len = sizeof(client); // 接受连接请求 connfd = accept(listenfd, (struct sockaddr *)&client, &len); if (connfd < 0) { std::cerr << "Error in accepting connection." << std::endl; return -1; } // 创建一个新的线程处理客户端连接 pthread_t threadid; pthread_create(&threadid, NULL, handle_client, (void*)&connfd); }
连接效果如图
可以看到,多个客户端同时连接访问,并发送接收消息都是没问题的。
该方式可以应对小量连接请求,客户端退出线程退出,在预估客户端同时使用不多的情况下是可用的。但毕竟多线程内存开销还是比较大的,在面对庞大的客户端访问时是非常不友好的。
标签:--,tcp,学习,buffer,client,服务器,include,连接,客户端 From: https://www.cnblogs.com/templeD/p/17488144.html