TCP/IP网络编程 第五章:实现基于TCP的服务端/客户端(2)
发布人:shili8
发布时间:2025-01-03 02:59
阅读次数:0
**TCP/IP网络编程**
**第五章: 实现基于TCP的服务端/客户端(2)**在前一章中,我们已经实现了一个简单的基于TCP的服务端和客户端程序。然而,这个程序存在一些问题,例如:
*服务端无法处理多个客户端连接* 客户端无法同时发送多条消息给服务端为了解决这些问题,我们需要对服务端和客户端进行改进。
**5.1服务端改进**
首先,让我们来看看如何改进服务端。我们可以使用一个线程池来处理多个客户端连接,这样就可以避免由于多个线程竞争资源而导致的性能问题。
cpp#include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define PORT12345class Server { public: Server() : _sockfd(-1), _threadPool(5) {} ~Server() { close(_sockfd); } void start() { // 创建套接字 _sockfd = socket(AF_INET, SOCK_STREAM,0); if (_sockfd < 0) { std::cerr << "socket error" << std::endl; return; } // 设置地址和端口号 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PORT); inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); // 绑定套接字到指定的地址和端口号上 if (bind(_sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { std::cerr << "bind error" << std::endl; return; } // 监听套接字,等待连接请求 listen(_sockfd,5); while (true) { struct sockaddr_in clientAddr; socklen_t clientLen = sizeof(clientAddr); int clientSockfd = accept(_sockfd, (struct sockaddr*)&clientAddr, &clientLen); if (clientSockfd < 0) { std::cerr << "accept error" << std::endl; continue; } // 将客户端连接添加到线程池中 _threadPool.add(clientSockfd); // 等待线程池处理完成 _threadPool.wait(); } } private: int _sockfd; ThreadPool _threadPool; }; class ThreadPool { public: void add(int sockfd) { _threads.push_back(std::make_shared<Thread>(sockfd)); } void wait() { for (auto& thread : _threads) { thread->join(); } _threads.clear(); } private: std::vector<std::shared_ptr<Thread>> _threads; }; class Thread { public: Thread(int sockfd) : _sockfd(sockfd), _running(false) {} void run() { if (!_running) { _running = true; // 处理客户端连接 while (true) { char buffer[1024]; int len = recv(_sockfd, buffer,1024,0); if (len < 0) { break; } // 处理消息 std::string message(buffer, len); // 发送回复消息 send(_sockfd, message.c_str(), message.size(),0); } } } private: int _sockfd; bool _running; };
**5.2 客户端改进**
同样,我们需要对客户端进行改进,以便能够同时发送多条消息给服务端。
cpp#include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define PORT12345class Client { public: Client() : _sockfd(-1) {} ~Client() { close(_sockfd); } void start() { // 创建套接字 _sockfd = socket(AF_INET, SOCK_STREAM,0); if (_sockfd < 0) { std::cerr << "socket error" << std::endl; return; } // 设置地址和端口号 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PORT); inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); // 连接服务端 if (connect(_sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { std::cerr << "connect error" << std::endl; return; } while (true) { char buffer[1024]; int len = recv(_sockfd, buffer,1024,0); if (len < 0) { break; } // 处理消息 std::string message(buffer, len); // 发送回复消息 send(_sockfd, message.c_str(), message.size(),0); } } private: int _sockfd; };
**5.3 总结**
在本章中,我们对服务端和客户端进行了改进,使得它们能够处理多个连接并同时发送多条消息。这些改进使得基于TCP的服务端/客户端程序更加高效和可靠。
然而,这些改进也带来了新的挑战,例如如何管理线程池、如何处理多个连接等问题。这些挑战需要我们深入研究网络编程的原理和技术,以便能够设计出高性能、高可靠性的服务端/客户端程序。
**参考**
* 《TCP/IP网络编程》第五章* 《Linux socket编程》第五章