免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1919 | 回复: 1
打印 上一主题 下一主题

程序为什么会发生丢失信号,怎么处理? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-12-19 15:12 |只看该作者 |倒序浏览
写了一个客户端和服务器端的通信程序,要求服务器端单线程实现异步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)
        {
                                                                                
        }
}

论坛徽章:
0
2 [报告]
发表于 2007-12-19 15:18 |只看该作者

回复 #1 wbchu 的帖子

/*这个是没有加sleep函数的客户端发送数据包,在服务器端看到的结果*/

[root@wbchu tmp]# ./main
from client,IP:192.168.4.236,Port:37561
SIGIO Received....
sock_fd have data to receive....
StartReplay:1
StartReplay:2
StartReplay:3
StartReplay:4
StartReplay:5
StartReplay:6
StartReplay:7
StartReplay:8
StartReplay:9
StartReplay:10
StartReplay:11
StartReplay:12
StartReplay:13
StartReplay:14
StartReplay:15
StartReplay:16
StartReplay:17
StartReplay:18
StartReplay:19
StartReplay:20
StartReplay:21
StartReplay:22
StartReplay:23
StartReplay:24
StartReplay:25
StartReplay:26
StartReplay:27
StartReplay:28
StartReplay:29
StartReplay:30

after signal processiong...


/*客户端加了sleep函数的结果(为了篇幅,没有拷全)*/
[root@wbchu tmp]# ./main
from client,IP:192.168.4.236,Port:37655
SIGIO Received....
sock_fd have data to receive....
StartReplay:1

after signal processiong...
SIGIO Received....
sock_fd have data to receive....
StartReplay:2

after signal processiong...
SIGIO Received....
sock_fd have data to receive....
StartReplay:3

after signal processiong...
SIGIO Received....
sock_fd have data to receive....
StartReplay:4


可以看出,客户端一次快速发送多个数据包会导致服务器端一个信号处理调用就接收多个数据,而非多次调用。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP