|
以前我写了一篇用SIGIO完成socket编程的帖子。
http://linuxsir.cn/bbs/showthread.php?t=214611
这篇文章采用一种更好的方法来完成。
发送端代码- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <netinet/in.h> /*socket address struct*/
- #include <arpa/inet.h> /*host to network convertion*/
- #include <sys/socket.h>
- #include <signal.h>
- #define MAX_TRANSPORT_LENTH 512
- int main()
- {
- struct sockaddr_in addr;
- memset(&addr,0,sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr("127.0.0.1");
- addr.sin_port = htons(50001);
-
- int sock;
- sock = socket(AF_INET,SOCK_DGRAM,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);
- }
- while(1)
- {
- printf("Will send messge to server\n");
- write(sock,"Some unknown infomation\n",MAX_TRANSPORT_LENTH);
- sleep(1);
- }
-
- }
复制代码 发送端同上篇帖子相比,没啥区别。
主要不同的在于接收端,因为是采用了aio,所以很有些不同
接收端代码- #include <aio.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <netinet/in.h> /*socket address struct*/
- #include <arpa/inet.h> /*host to network convertion*/
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <signal.h>
- //#include <sys/ioctl.h>
- #define MAX_TRANSPORT_LENTH 512
- #define MAX_LIST 5
- void sig_handler(int signo, siginfo_t *info, void *context )
- {
- int ret;
- struct aiocb *req;
- /* Ensure it's our signal */
- if (info->si_signo == SIGIO) {
- req = (struct aiocb *)info->si_value.sival_ptr;
- if (aio_error( req ) == 0) {
- ret = aio_return( req );
- (char*)(req->aio_buf+ret) == '\0';//通常是拷贝一下数据,交给线程池去处理,以空间换取时间,从而加快主循环
- puts(req->aio_buf);
- }
- }
- return;
- }
- int main()
- {
- int skt_fd,ret;
- struct aiocb my_aiocb;
- struct sigaction sig_act;
-
- struct sockaddr_in addr;
- memset(&addr,0,sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = htons(50001);
-
-
- skt_fd = socket(AF_INET, SOCK_DGRAM, 0);
- if(skt_fd == -1)
- {
- perror("Create socket failed");
- exit(-1);
- }
- ret = bind(skt_fd,(struct sockaddr *)&addr,sizeof(addr));
- if(-1 == ret)
- {
- perror("Bind socket failed");
- exit(-1);
- }
- memset(&my_aiocb,0,sizeof(my_aiocb));
- my_aiocb.aio_buf = malloc(MAX_TRANSPORT_LENTH+1);
- if (!my_aiocb.aio_buf)
- perror("malloc");
-
- my_aiocb.aio_fildes = skt_fd;
- my_aiocb.aio_nbytes = MAX_TRANSPORT_LENTH;
- my_aiocb.aio_offset = 0;
-
- my_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
- my_aiocb.aio_sigevent.sigev_signo = SIGIO;
- my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;
-
- sigemptyset(&sig_act.sa_mask);
- sig_act.sa_flags = SA_SIGINFO;
- sig_act.sa_sigaction = sig_handler;
-
- const struct aiocb *cblist[MAX_LIST] ={&my_aiocb,NULL,NULL,NULL,NULL};
- sigaction( SIGIO, &sig_act, NULL );
-
- ret = aio_read( &my_aiocb );
- //程序挂起直到等到某个信号
- while ( aio_suspend( cblist, MAX_LIST, NULL ) == 0)
- {
- ret = aio_read( &my_aiocb );
- };
- puts("Interrupted finish.");
- close(skt_fd);
- }
复制代码 在这里,如果用my_aiocb.aio_sigevent.sigev_notify = SIGEV_THREAD;
则可以指定一个回调函数来完成读取数据的操作,这种方法还是希望对此文感兴趣的伙伴加以完善吧。 |
|