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编程》第五章

