v
對於linux socket通信,幾個基本流程
sockfd=socket(AF_INET,SOCK_STREAM,0);
bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
listen(sockfd,most_connect);
acceptfd=accept(sockfd,(struct sockaddr*)&client_addr,&len);
過後就是一個while循環,和客戶端之間的read,write;
#include <poll.h>//poll函數包含在此庫裏。
#include <poll.h>
const struct timespec *timeout, const sigset_t *sigmask);
poll() performs a similar task to select(2): it waits for one of a set of file descriptors to become ready to perform I/O.
int fd; /* file descriptor文件描述符*/
short events; /* requested events等待的事件 */
short revents; /* returned events實際發生的事件 */
};
POLLIN There is data to read.d讀事件
POLLPRI
There is urgent data to read 高級的讀事件
POLLOUT
Writing now will not block.寫事件
POLLERR
Error condition (output only).錯誤事件
POLLHUP
Hang up (output only).錯誤事件
POLLNVAL
Invalid request: fd not open (output only).錯誤事件
代碼實例:
#include <stdio.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <poll.h>
#include <unistd.h>
#include <sys/socket.h>
#define PROT 6666
#define SOMAXCON 10
#define OPEN_MAX 1024
int main()
{
int P;
int maxi;
int sockfd,bindnes,acceptfd;
int on = 1;
int i;
char buf[1024];
struct sockaddr_in server_addr,client_addr;
struct pollfd client[OPEN_MAX];此處創建結構體數組client[];
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
{
printf("create socket fail%s\n",strerror(errno));
exit(-1);
}
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(PROT);
server_addr.sin_addr.s_addr=INADDR_ANY;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
bindnes = bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
if(bindnes < 0)
{
printf("bind fail%s\n",strerror(errno));
exit(-1);
}
if(listen(sockfd,SOMAXCON)<0)
{
printf("listen fail%s\n",strerror(errno));
exit(-1);
}
printf("waiting connection\n");
client[0].fd=sockfd;//此client第一個描述符賦值爲sockfd,事件爲讀事件。
client[0].events=POLLIN;
for(i=1;i<OPEN_MAX;i++)
{
client[i].fd = -1;此後先把除第一個以外所有的fd初始值爲-1
}
maxi=0;描述符個數
for(;;)
{
P=poll(client,maxi+1,-1);//poll函數
if(P<0)
{
printf("poll fail%s\n",strerror(errno));
break;
}
if(P==0)
{
printf("time out %s\n",strerror(errno));超時過後繼續等待事件
continue;
}
printf("poll ok!\n");
if(client[0].revents & POLLIN)判斷是發生client[0]的事件而且爲讀事件。
{
socklen_t len=sizeof(client_addr);
acceptfd=accept(sockfd,(struct sockaddr*)&client_addr,&len);過後accept
if(acceptfd < 0)
{
printf("accept fail%s\n",strerror(errno));
break;
}
for(i=1;i<OPEN_MAX;i++)
{
if(client[i].fd < 0)
{
client[i].fd=acceptfd;將acceptfd該文件描述符添加到client[]這個文件描述符集中
break;
}
if(OPEN_MAX==i)
{
printf("too many connection%s\n");
exit(-1);
}
if(maxi<i)
{
maxi=i;
}
if(--P<=0)
continue;
}
for(i=0;i<OPEN_MAX;i++)
{
if(client[i].fd < 0) continue;
if(client[i].revents & POLLIN)//再次遍歷文件描述符集,遍歷到accpetfd文件描述符,切爲讀操作
{
while(1)
{
int n = read(acceptfd,buf,sizeof(buf));過後通過read函數讀取客戶端發送的數據
if(n == 0)
{
close(client[i].fd);客戶端關閉過後關閉該文件描述符,此後該fd重新置爲-1
client[i].fd=-1;
continue;
}
if(n < 0)
{
printf("read fail%s\n",strerror(errno));
exit(-1);
}
printf("read %d bytes, data %s\n\n",n,buf);
write(acceptfd,buf,n);
}
}
}
}
}
return 0;
}