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;
}