- 论坛徽章:
- 0
|
写了一个客户端和服务器端的通信程序,要求服务器端单线程实现异步IO。下面的服务器程序采用了信号驱动IO模型,即在客户端发过来的TCP数据包到达的时候内核以SIGIO信号通知服务器进程执行接收操作。执行时通过打印输出发现客户端发数据包太快的时候,服务器端并不是每到一个数据包就调用一次信号处理函数(客户端中sleep函数的作用就是为了调节发包速度),而是一次就接收多个数据包。并且在连接服务器完成之后,马上只发送一个数据包,并不会引起服务器相应的信号处理函数调用。这是怎么回事?如果我想每收到一个数据包就接收一次,该怎么处理?各位能否指点一下。
/*服务器端代码*/
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#define SERVER_PORT_TCP 4000 // define the defualt connect port id
#define SERVER_PORT_UDP 2001
#define LENGTH_OF_LISTEN_QUEUE 10 //length of listen queue in server
#define BUFFER_SIZE 1500
#define WELCOME_MESSAGE "welcome to connect the server."
int clifd;
fd_set readfds;
struct timeval tv;
struct sigaction action;
void read_socket(int sig)
{
printf("SIGIO Received....\n");
select(clifd+1, &readfds, NULL, NULL, &tv);
if(FD_ISSET(clifd, &readfds))
{
printf("sock_fd have data to receive....\n");
char buf[1500];
memset(buf, 0, 1500);
int n;
//do
{
if(n=recv(clifd, buf, 1500, 0)<0)
{
if(errno==EWOULDBLOCK)
{
return;
}
}else
{
if(buf[0]=='S')
{
printf("%s\n", buf);
}
}
}//while(0);
}
printf("after signal processiong...\n");
}
int main(int argc, char **argv)
{
int servfd;
struct sockaddr_in servaddr,cliaddr;
tv.tv_sec=0;
tv.tv_usec=0;
sigset_t newmask, oldmask;
memset(&action, 0, sizeof(action));
action.sa_handler = read_socket;
action.sa_flags = 0;
sigemptyset(&action.sa_mask);
sigaction(SIGIO, &action, NULL);
//signal(SIGIO, read_socket);
if ((servfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
printf("create socket error!\n");
exit(1);
}
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVER_PORT_TCP);
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
if (bind(servfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
{
printf("bind to port %d failure!\n",SERVER_PORT_TCP);
exit(1);
}
if (listen(servfd,LENGTH_OF_LISTEN_QUEUE) < 0)
{
printf("call listen failure!\n");
exit(1);
}
socklen_t length = sizeof(cliaddr);
clifd = accept(servfd,(struct sockaddr*)&cliaddr,&length);
fcntl(clifd, F_SETOWN, getpid());
fcntl(clifd, F_SETFL, O_ASYNC);
//fcntl(clifd, F_SETFL, O_NONBLOCK);
int on=1;
//fcntl(clifd, FIOASYNC, &on);
//fcntl(clifd, FIONBIO, &on);
FD_ZERO(&readfds);
FD_SET(clifd, &readfds);
printf("from client,IP:%s,Port:%d\n",inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
while(1)
{
}
}
/*客户端代码*/
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <time.h>
int main()
{
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.4.236");
addr.sin_port = htons(4000);
int sock;
sock = socket(AF_INET,SOCK_STREAM,0);
if(sock == -1)
{
perror("Create socket failed");
exit(-1);
}
int ret;
ret = connect(sock,(struct sockaddr *)&addr,sizeof(addr));
if(ret == -1)
{
perror("Connect socket failed");
exit(-1);
}
//sleep(2);
int i=1;
char tcp_buf[1500];
memset(tcp_buf, 0, 1500);
sprintf(tcp_buf, "StartReplay:%d\n", i);
if(send(sock, tcp_buf, strlen(tcp_buf), 0)<=0)
{
printf("send error....\n");
exit(1);
}
while(i<30)
{
//sleep(1);
i++;
memset(tcp_buf, 0, 1500);
sprintf(tcp_buf, "StartReplay:%d\n", i);
if(send(sock, tcp_buf, strlen(tcp_buf), 0)<=0)
{
printf("send error....\n");
exit(1);
}
}
while(1)
{
}
} |
|