网站域名过期怎么做,学会网站制作要多久,福州网站建设网站设计网站推广,软件公司介绍TCP并发服务器的多进程实现与多线程实现
一、 TCP并发服务器的多进程实现
代码
#include my_head.h#define SERVER_IP 192.168.125.11 // 服务器IP
#define SERVER_PORT 6666 // 服务器端口// 子进程处理客户端信息函数
int deal_client_me…TCP并发服务器的多进程实现与多线程实现
一、 TCP并发服务器的多进程实现
代码
#include my_head.h#define SERVER_IP 192.168.125.11 // 服务器IP
#define SERVER_PORT 6666 // 服务器端口// 子进程处理客户端信息函数
int deal_client_message(int new_sfd, struct sockaddr_in client_info);
// 回调函数回收僵尸进程函数
void callBack_zembie(int sig);int main(int argc, const char *argv[])
{// 用信号的方式回收僵尸进程if (signal(SIGCHLD, callBack_zembie) 0){ERR_MSG(signal);return -1;}// 创建流式套接字int sfd socket(AF_INET, SOCK_STREAM, 0);if (sfd 0){ERR_MSG(socket);return -1;}// 待绑定的服务器的信息struct sockaddr_in server_info;server_info.sin_addr.s_addr inet_addr(SERVER_IP);server_info.sin_port htons(SERVER_PORT);server_info.sin_family AF_INET;// 绑定if (bind(sfd, (struct sockaddr *)server_info, sizeof(server_info)) 0){ERR_MSG(bind);return -1;}// 监听if (listen(sfd, 128) 0){ERR_MSG(listen);return -1;}// 客户端连接过来的信息struct sockaddr_in client_info;socklen_t len sizeof(client_info);// 用于接收客户端连接的文件描述符int new_sfd;// 子进程的 pidpid_t cpid -1;while (1){// 连接acceptnew_sfd accept(sfd, (struct sockaddr *)client_info, len);if (new_sfd 0){ERR_MSG(accept);return -1;}printf([%s : %d]已连接 new_fd %d \n, inet_ntoa(client_info.sin_addr),ntohs(client_info.sin_port), new_sfd);// 创建子进程用于处理接收的信息cpid fork();// 子进程进行处理if (0 cpid){// 关闭父进程的服务器文件描述符close(sfd);// 调用函数进行处理消息deal_client_message(new_sfd, client_info);// 关闭新创建的用于接收客户端传来信息的文件描述符close(new_sfd);// 结束进程当前进程为子进程exit(0);}else if (cpid 0){ERR_MSG(fork);return -1;}// 下边这部分是父进程的内容// 在此次循环中关闭新建的文件描述符因为下次循环又会创建了close(new_sfd);}// 关闭套接字close(sfd);return 0;
}// 回调函数回收僵尸进程函数功能实现
void callBack_zembie(int sig)
{// 回收僵尸进程资源while (waitpid(-1, NULL, WNOHANG) 0);
}// 子进程处理客户端信息函数功能实现
int deal_client_message(int new_sfd, struct sockaddr_in client_info)
{char buff[128];ssize_t res -1;while (1){bzero(buff, sizeof(buff));// 接收消息以阻塞方式接收res recv(new_sfd, buff, sizeof(buff), 0);if (res 0){ERR_MSG(recv);break;}else if (0 res){// 客户端掉线printf([%s : %d] 已掉线\n, inet_ntoa(client_info.sin_addr),ntohs(client_info.sin_port));break;}// 将消息输出printf([%s : %d][message : %s]\n, inet_ntoa(client_info.sin_addr),ntohs(client_info.sin_port), buff);// 判断客户端是否断开链接if (!strcmp(buff, exit)){printf([%s : %d] 断开链接\n, inet_ntoa(client_info.sin_addr),ntohs(client_info.sin_port));break;}strcat(buff, ---);// 处理消息(可以是回复)if (send(new_sfd, buff, sizeof(buff), 0) 0){ERR_MSG(send);break;}}// 关闭文件描述符close(new_sfd);return 0;
}二、 TCP并发服务器的多线程实现
#include my_head.h#define SERVER_IP 192.168.125.11 // 服务器IP
#define SERVER_PORT 6666 // 服务器端口struct client_information
{int new_sfd;struct sockaddr_in info;
};// 线程处理客户端信息函数
void *thread1(void *arg);int main(int argc, const char *argv[])
{// 创建流式套接字int sfd socket(AF_INET, SOCK_STREAM, 0);if (sfd 0){ERR_MSG(sfd);return -1;}// 服务器信息struct sockaddr_in server_info;server_info.sin_addr.s_addr inet_addr(SERVER_IP);server_info.sin_port htons(SERVER_PORT);server_info.sin_family AF_INET;// 绑定if (bind(sfd, (struct sockaddr *)server_info, sizeof(server_info)) 0){ERR_MSG(bind);return -1;}// 监听if (listen(sfd, 128) 0){ERR_MSG(listen);return -1;}// 客户端信息struct client_information client_info;socklen_t len sizeof(client_info.info);// 子线程号pthread_t tid;while (1){// 连接acceptclient_info.new_sfd accept(sfd, (struct sockaddr *)(client_info.info), len);if (client_info.new_sfd 0){ERR_MSG(accept);return -1;}printf([%s : %d]已连接 new_fd %d \n, inet_ntoa(client_info.info.sin_addr),ntohs(client_info.info.sin_port), client_info.new_sfd);// 创建子线程if (pthread_create(tid, NULL, thread1, client_info) 0){fprintf(stderr, 线程创建出错 __%d__\n, __LINE__);return -1;}// 将线程分离待线程结束后可以直接被操作系统回收pthread_detach(tid);}// 关闭套接字close(client_info.new_sfd);close(sfd);return 0;
}// 线程处理客户端信息函数功能实现
void *thread1(void *arg)
{struct client_information client_info *((struct client_information *)arg);ssize_t res -1;char buff[128];while (1){bzero(buff, sizeof(buff));// 接收客户端传来的信息res recv(client_info.new_sfd, buff, sizeof(buff), 0);if (res 0){ERR_MSG(recv);break;}else if (0 res){// 客户端掉线printf([%s : %d] 已掉线\n, inet_ntoa(client_info.info.sin_addr),ntohs(client_info.info.sin_port));break;}/** 处理回复 */// 将消息输出printf([%s : %d][message : %s]\n, inet_ntoa(client_info.info.sin_addr),ntohs(client_info.info.sin_port), buff);// 判断客户端是否退出if (!strcmp(buff, exit)){printf([%s : %d] 断开链接\n, inet_ntoa(client_info.info.sin_addr),ntohs(client_info.info.sin_port));break;}strcat(buff, ---);// 处理消息(可以是回复)if (send(client_info.new_sfd, buff, sizeof(buff), 0) 0){ERR_MSG(send);break;}}// 关闭文件描述符close(client_info.new_sfd);// 退出线程pthread_exit(NULL);
}