刚刚我们实现了一个TCP通信, 但是效果不太理想, 那么我们来实现一个能和多用户连续通信的TCP吧~
原因分析
我们的TCP之所以只能和用户进行单此通信, 是因为主进程要完成的事情太多了, 他既要获取新连接, 又要与用户进行通信
如果我们让一个执行流只负责一件事情, 就算某个执行流阻塞了, 也不会影响其他的执行流
因此我们有两种实现方式
- 多进程
- 多线程
多进程实现并发服务器
主进程只负责获取新连接, 有新连接获取成功, 则创建子进程负责与客户端进行通信
具体代码如下:
#include "tcpsocket.hpp"
#include <signal.h>
#include <sys/wait.h>
void sigcb(int signo) {
while(waitpid(-1, NULL, WNOHANG) > 0);
}
int main() {
signal(SIGCHLD, sigcb);
//监听套接字
TcpSocket lst_sock;
//1.创建套接字
CHECK_RET(lst_sock.Socket());
//2.绑定地址信息
CHECK_RET(lst_sock.Bind("0.0.0.0", 9000));
//3.开始监听
CHECK_RET(lst_sock.Listen());
while(1) {
//4.获取新连接
TcpSocket con_sock;
string cli_ip;
int cli_port;
int ret = lst_sock.Accept(&con_sock, &cli_ip, &cli_port);
if (ret == false) {
//获取失败就重新去获取
continue;
}
//多进程通信
pid_t pid = fork();
if (pid < 0) {
con_sock.Close();
continue;
}
else if (pid == 0) {
//子进程
while(1) {
//5.收发数据
string buf;
ret = con_sock.Recv(&buf);
if (ret == false) {
con_sock.Close();
continue;
}
printf("[%s:%d] say:%s\n", cli_ip.c_str(), cli_port, buf.c_str());
string data;
cout << "server say: ";
cin >> data;
ret = con_sock.Send(data);
if (ret == false) {
con_sock.Close();
continue;
}
}
exit(0);
}
//能走下来就是父进程
//父子进程数据独有, 但是父进程不通信
//所以要关闭父进程套接字,不关闭就会资源泄漏
con_sock.Close();
}
//6.关闭套接字
lst_sock.Close();
return 0;
}
注意:
1. 因为父子进程数据独有, 父进程不进行通信, 所以父进程一定要关闭套接字, 否则会资源泄漏
2. 要注意僵尸子进程的处理, 使用信号进行处理
多线程实现并发服务器
主线程只负责获取新连接, 有新连接获取成功, 则创建子线程, 子线程负责与客户端通信
具体代码如下 :
#include "tcpsocket.hpp"
#include <pthread.h>
void* thr_start(void* arg) {
TcpSocket* con_sock = (TcpSocket*)arg;
while(1) {
string buf;
int ret = con_sock->Recv(&buf);
if (ret == false) {
con_sock->Close();
delete con_sock;
return NULL;
}
printf("client say:%s\n", buf.c_str());
string data;
cout << "server say: ";
cin >> data;
ret = con_sock->Send(data);
if (ret == false) {
con_sock->Close();
delete con_sock;
return NULL;
}
}
delete con_sock;
return NULL;
}
int main() {
//监听套接字
TcpSocket lst_sock;
//1.创建套接字
CHECK_RET(lst_sock.Socket());
//2.绑定地址信息
CHECK_RET(lst_sock.Bind("0.0.0.0", 9000));
//3.开始监听
CHECK_RET(lst_sock.Listen());
while(1) {
//4.获取新连接
TcpSocket* con_sock = new TcpSocket();
int ret = lst_sock.Accept(con_sock);
if (ret == false) {
//获取失败就重新去获取
continue;
}
pthread_t tid;
pthread_create(&tid, NULL, thr_start, (void*)con_sock);
pthread_detach(tid);
}
//6.关闭套接字
lst_sock.Close();
return 0;
}
描述符通过参数传递给子线程
线程之间共享文件描述符, 虽然主线程不通信, 但是也不能关闭主线程的套接字
这样就实现了与多个用户进行连续通信, 大家可以自行编译测试~
1910

被折叠的 条评论
为什么被折叠?



