資源簡介
在學習《UNIX網絡編程》基礎上自己動手實現TCP服務器和客戶端通訊,這個版本是進階版程序——實現多個客戶端的之間的通訊。程序包含了常規網絡通訊的主要步驟,除此之外還運用了select()和poll()等技術,具有一定難度,程序思路清晰,代碼注釋詳細,適合有一定基礎的人學習。代碼已經無誤通過測試。初學者可以休息我的入門版程序——實現單個客戶端的之間的通訊,可見我的其他資源。

代碼片段和文件信息
/*服務器端程序:一個服務器和多個客戶端通訊(復用)*/
#include????
#include????
#include????
#include????
#include????
#include????
#include????
#include?
#include?
#include?
#define?BUFFER_SIZE?1024????
int?main(int?argc?const?char?*?argv[])????
{???
????int?in;
????int?connfdsockfd;
????struct?epoll_event?evevents[20];?//ev用于注冊事件數組用于回傳要處理的事件,告訴內核要監聽什么事
????//============創建一個epoll的句柄,其中256為你epoll所支持的最大句柄數==========
????int?epfd=epoll_create(256);//創建一個epoll的句柄,其中256為你epoll所支持的最大句柄數
????struct?sockaddr_in?client_addr;
????struct?sockaddr_in?server_addr;????
????server_addr.sin_family?=?AF_INET;????
????server_addr.sin_port?=?htons(11277);????
????server_addr.sin_addr.s_addr?=INADDR_ANY;????
????bzero(&(server_addr.sin_zero)?8);????
????int?server_sock_fd?=?socket(AF_INET?SOCK_STREAM?0);??
????ev.data.fd=server_sock_fd; //設置與要處理的事件相關的文件描述符
????//ev.events=EPOLLIN|EPOLLOUT|EPOLLET; //設置要處理的事件類型,可讀可寫
ev.events=EPOLLIN|EPOLLET; //設置要處理的事件類型先監聽狀態,讀數據然后再根據需求修改
//============注冊epoll事件====================
????epoll_ctl(epfdEPOLL_CTL_ADDserver_sock_fd&ev);
????if(server_sock_fd?==?-1)????
????{????
????????perror(“socket?error“);????
????????return?1;????
????}????
????char?recv_msg[BUFFER_SIZE];????
????char?input_msg[BUFFER_SIZE];????
????if(connect(server_sock_fd?(struct?sockaddr?*)&server_addr?sizeof(struct?sockaddr_in))?==?0)????
????{????
????????for(;;)
????????{
//================等待epoll事件的發生=================
????????????int?nfds=epoll_wait(epfdevents20500);
????????????for(i=0;i ????????????{????
????????????????if(events[i].events&EPOLLOUT)? //監測事件類型,若有數據發送,寫socket
????????????????{
printf(“send?message?to?server:?“);
????????????????????bzero(input_msg?BUFFER_SIZE);????
????????????????????fgets(input_msg?BUFFER_SIZE?stdin);????
????????????????????sockfd?=?events[i].data.fd;
????????????????????//write(sockfd?recv_msg?n);
write(sockfd?input_msg?BUFFER_SIZE);
//send(sockfdinput_msgBUFFER_SIZE0);
????????????????????ev.data.fd=sockfd;
????????????????????ev.events=EPOLLIN|EPOLLET; //寫完數據后,將事件類型變為讀操作
????????????????????epoll_ctl(epfdEPOLL_CTL_MODsockfd&ev); //修改后需要重新注冊,這里使用EPOLL_CTL_ADD就會出錯
????????????????}???
????????????????else?if(events[i].events&EPOLLIN) //監測事件類型,若有數據到來,讀socket
????????????????{
????????????????????bzero(recv_msg?BUFFER_SIZE);
????????????????????if((n?=?read(server_sock_fd?recv_msg?BUFFER_SIZE))?<0?)
????????????????????{
????????????????????????printf(“read?error!“);
????????????????????}?
????????????????????ev.data.fd=server_sock_fd;
????????????????????ev.events=EPOLLOUT|EPOLLET; //讀完數據后,將事件類型變為寫操作
????????????????????printf(“message?from?server:?%s\n“recv_msg);
epoll_ctl(epfdEPOLL_CTL_MODserver_sock_fd&ev); //修改后需要重新注冊,這里使用EPOLL_CTL_ADD就會出錯
????????????????}
????????????}????????
????????}
????}????
????return?0;????
}???
?屬性????????????大小?????日期????時間???名稱
-----------?---------??----------?-----??----
?????文件???????6937??2018-06-10?17:15??server5.c
?????文件???????3513??2018-06-10?17:20??client5.c
-----------?---------??----------?-----??----
????????????????10450????????????????????2
評論
共有 條評論