隨筆-1  評(píng)論-0  文章-0  trackbacks-0
          關(guān)于linux socket編程的lecture
          http://www.aka.org.cn/Lectures/002/Lecture-2.1.8/Lecture-2.1.8/index.htm

          阻塞模式

          socket的缺省方式,也是最常用的方式,即函數(shù)阻塞直到調(diào)用完畢。

          可能造成阻塞的函數(shù)有:recvfrom() 、connect()、accept()、讀寫函數(shù)、select()、poll()、gethostbyname()等。

          ????????????????

          #include <stdio.h>
          #include <stdlib.h>
          #include <errno.h>
          #include <string.h>
          #include <sys/types.h>
          #include <netinet/in.h>
          #include <sys/socket.h>
          #include <sys/wait.h>
          #define MYPORT 3490??????????????? ? /* 監(jiān)聽(tīng)的端口 */
          #define BACKLOG 10??????????????? ?? /* listen的請(qǐng)求接收隊(duì)列長(zhǎng)度 *

          void main() {

          int sockfd, new_fd;??????????? /* 監(jiān)聽(tīng)端口,數(shù)據(jù)端口 */
          struct sockaddr_in sa;???????? /* 自身的地址信息 */
          struct sockaddr_in their_addr; /* 連接對(duì)方的地址信息 */
          int sin_size;

          if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {??
          ??? perror("socket");
          ??? exit(1);
          }
          sa.sin_family = AF_INET;
          sa.sin_port = htons(MYPORT);???????? /* 網(wǎng)絡(luò)字節(jié)順序 */
          sa.sin_addr.s_addr = INADDR_ANY;???? /* 自動(dòng)填本機(jī)IP */
          bzero(&(sa.sin_zero), 8);???????????? /* 其余部分置0 */
          if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {??
          ??? perror("bind");
          ??? exit(1);
          }
          if (listen(sockfd, BACKLOG) == -1) {??
          ??? perror("listen");
          ??? exit(1);
          }
          /* 主循環(huán) */

          while(1) {
          ??? sin_size = sizeof(struct sockaddr_in);
          ??? new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size));
          ??? if (new_fd == -1) {
          ??? ??? perror("accept");
          ??? ??? continue;
          ??? }
          ??? printf(”Got connection from %s\n", inet_ntoa(their_addr.sin_addr));
          ??? if (fork() == 0) {??? /* 子進(jìn)程 */?? ??
          ??? ??? if (send(new_fd, "Hello, world!\ n", 14, 0) == -1)?? ??
          ??? ??? ??? perror("send");
          ??? ??? ??? close(new_fd);
          ??? ??? ??? exit(0);
          ??? }
          ??? close(new_fd);??? /*清除所有子進(jìn)程 */
          ??? while(waitpid(-1,NULL,WNOHANG) > 0);
          ?}
          }


          非阻塞模式

          程序調(diào)用可能造成阻塞的函數(shù)時(shí):
          如果會(huì)發(fā)生阻塞,這些函數(shù)返回-1并將errno設(shè)置為EAGAIN或EWOULDBLOCK,程序可繼續(xù)向下運(yùn)行。可能阻塞
          的函數(shù)對(duì)應(yīng)的任務(wù)完成,則再次調(diào)用該函數(shù)時(shí)就返回0表示運(yùn)行結(jié)束

          非 阻塞模式可以避免程序死鎖,但是需要程序不斷檢查各個(gè)可能阻塞的函數(shù)的狀態(tài),當(dāng)一個(gè)應(yīng)用程序使用了
          非阻塞模式的套接字,它需要使用一個(gè)循環(huán)來(lái)不聽(tīng)的測(cè)試是 否一個(gè)文件描述符有數(shù)據(jù)可讀(稱做polling)。
          應(yīng)用程序不停的polling內(nèi)核來(lái)檢查是否I/O操作已經(jīng)就緒。這將是一個(gè)極浪費(fèi)CPU資源的操 作,因此不能實(shí)際
          應(yīng)用。一般非阻塞模式是與同步I/O模式共同使用的。


          ?

          獲得或改變socket的I/O屬性:

          int ioctl(int sockfd,long cmd,unsigned long* argp);

          cmd屬性類型,argp屬性的參數(shù)。
          常用的有:
          FIONREAD,返回socket緩沖區(qū)中未讀數(shù)據(jù)的字節(jié)數(shù)
          FIONBIO,argp為零時(shí)為阻塞模式,非零時(shí)為非阻塞模式
          SIOCATMARK ,判斷是否有未讀的帶外數(shù)據(jù)(僅用于TCP協(xié)議),返回true或false

          int fcntl(int fd, int cmd, long arg);

          F_SETFL,arp為O_NONBLOCK時(shí)進(jìn)入非阻塞模式,為0時(shí)進(jìn)入阻塞模式。
          F_GETFL,獲得屬性。


          I/O多路復(fù)用(同步I/O模式)

          ???? 使用select()、poll()等函數(shù)實(shí)現(xiàn)對(duì)多個(gè)socket的同步I/O操作。它能同時(shí)等待多個(gè)
          socket描述符,而這些socket描述符其中的任意一個(gè)進(jìn)入讀就緒/寫就緒/出錯(cuò)狀態(tài),select()
          函數(shù)就可以返回。

          ??? ??

          ??????

          socket輪詢選擇:

          int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

          應(yīng)用于多路同步I/O模式


          FD_ZERO(*set) 清空socket集合

          FD_SET(s, *set) 將s加入socket集合

          FD_CLR(s, *set) 從socket集合去掉s

          FD_ISSET(s, *set) 判斷s是否在socket集合

          ???? 常數(shù)FD_SETSIZE:集合元素的最多個(gè)數(shù)

          等待選擇機(jī)制:

          int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
          是select機(jī)制的一個(gè)變種,應(yīng)用于多路同步I/O模式
          ufds是pollfd結(jié)構(gòu)的數(shù)組,數(shù)組元素個(gè)數(shù)為nfds。

          struct pollfd {
          int fd; /* file descriptor */
          short events; /* requested events */
          short revents; /* returned events */
          };
          程序段節(jié)選int listenfd, connfd, maxfd=0;
          int nready;
          fd_set rset, allset;
          struct sockaddr_in cliaddr, servaddr;
          int clilen;
          listenfd = socket(AF_INET, SOCK_STREAM, 0);
          if (listenfd > maxfd) maxfd = listenfd;
          memset(&servaddr, 0, sizeof(servaddr));
          servaddr.sin_family = AF_INET;
          servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
          servaddr.sin_port = htons(4321);
          bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
          FD_ZERO(&allset);
          FD_SET(listenfd, &allset);
          listen(listenfd, 10);
          /* main loop */
          while (1) {
          rset = allset;
          nready = select(maxfd+1, &rset, NULL, NULL, NULL);
          if (FD_ISSET(listenfd, &rset)) {
          /* 有新的客戶端連接請(qǐng)求
          clilen = sizeof(cliaddr);
          connfd = accept(listenfd, (struct sockaddr*)&cliaddr,&clilen);
          if (client_num == FD_SETSIZE) {
          fprintf(stderr, "too many clients\n");
          exit(-1);
          }
          FD_SET(connfd, &allset);
          if (connfd > maxfd) maxfd = connfd;
          if (--nready <= 0) continue;
          }
          //以下依次判斷FD_ISSET(某個(gè)socket, &rset) 并做相應(yīng)處理
          }

          信號(hào)驅(qū)動(dòng)I/O

          ? ?? ?????????????

          異步I/O



          posted on 2006-04-13 10:29 steven's home 閱讀(920) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 余姚市| 南昌县| 两当县| 会昌县| 吉林省| 巴里| 平南县| 永新县| 昆明市| 靖宇县| 日喀则市| 岱山县| 汤阴县| 渑池县| 宁陕县| 甘肃省| 都匀市| 岑巩县| 怀化市| 万宁市| 张家界市| 海口市| 随州市| 泗阳县| 永昌县| 融水| 蕉岭县| 宜春市| 青海省| 遂昌县| 刚察县| 石台县| 基隆市| 乌鲁木齐县| 诸城市| 景泰县| 霞浦县| 工布江达县| 呼伦贝尔市| 开江县| 高台县|