• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0

            回顧:
              多進程的問題:數據共享。
              多進程的問題: 進程的上下文環境(context)
                      文件描述符號是整數以及對應上下文環境
              多進程的問題:上下文環境共享

            一.SELECT TCP服務器編程模式
             1.select函數
              int select(
               int fds,//建議是監控的文件描述符號的最大值+1
               fd_set *readfds,//讀文件描述符號集合
                       //該參數既是輸入,也是輸出
                       //輸入:被監控的描述符號
                       //輸出:有數據的描述符號
               fd_set *writefds,
               fd_set *errfds,
               struct timeval*timeout);//指定阻塞時間限制
                           //為NULL,永久
              返回:
                >0:發生改變的文件描述符號個數
                =0:時間限制過期
                =-1:異常  


            //select用法
            #include <stdio.h>
            #include <fcntl.h>
            #include <signal.h>
            #include <unistd.h>
            #include <sys/select.h>
            main()
            {    
                fd_set fds;
                int r;
                char buf[100];
                while(1)
                {
                    FD_ZERO(&fds);  //清空
                    FD_SET(0,&fds);  //將描述符0加入
                    r=select(1,&fds,0,0,0);  //監控
                    printf("有數據輸入!\n");
                    r=read(0,buf,99);
                }
            }
             2.IO能否發出信號?
               異步IO就是通過信號工作.
             3.應用使用select
             4.使用select實現TCP的多客戶連接與處理
            看個小例子: 

            //chatServer.c
            //聊天服務器端
            #include <stdio.h>
            #include <stdlib.h>
            #include <unistd.h>
            #include <string.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>
            #include <sys/select.h>
            main()
            {
                int sfd;//服務器描述符號
                int fdall[100];//客戶描述符號
                int count;//客戶個數
                int r;//返回值(異常處理)
                struct sockaddr_in dr;//IP地址與端口
                fd_set fds;//被select監控的描述符號集合
                int maxfd;//最大文件描述符號
                int i,j;//循環變量
                char buf[1024];//客戶聊天數據
                
                
            //1.建立socket
                sfd=socket(AF_INET,SOCK_STREAM,0);
                if(sfd==-1) printf("1:%m\n"),exit(-1);
                printf("socket ok!\n");
                //2.綁定地址與端口
                dr.sin_family=AF_INET;
                dr.sin_port=htons(8866);
                inet_aton("192.168.180.92",&dr.sin_addr);
                r=bind(sfd,(struct sockaddr*)&dr,sizeof(dr));
                if(r==-1) printf("2:%m\n"),close(sfd),exit(-1);
                printf("bind ok!\n");
                //3.監聽
                r=listen(sfd,10);
                if(r==-1) printf("3:%m\n"),close(sfd),exit(-1);
                printf("listen ok!\n");
                //初始化
                count=0;
                maxfd=0;
                FD_ZERO(&fds);
                for(i=0;i<100;i++)
                {
                    fdall[i]=-1;
                }
                while(1)
                {
                    //4.構造監聽的描述符號集合
                    
            //4.1.清空
                    FD_ZERO(&fds);
                    maxfd=0;
                    //4.2.加入服務器描述符號
                    FD_SET(sfd,&fds);
                    maxfd=maxfd>=sfd?maxfd:sfd;
                    //4.3.加入客戶描述符號
                    for(i=0;i<count;i++)
                    {
                        if(fdall[i]!=-1)
                        {
                            FD_SET(fdall[i],&fds);
                            maxfd=maxfd>=fdall[i]?maxfd:fdall[i];
                        }
                    }
                    //5.使用select循環控制描述符號集合
                    r=select(maxfd+1,&fds,0,0,0);
                    if(r==-1) 
                    {
                        printf("服務器崩潰!\n");
                        break;
                    }        
                    //6.分兩種情況處理:        
                    
            //6.1.有客戶連接:服務器描述符號
                    if(FD_ISSET(sfd,&fds))
                    {
                        fdall[count]=accept(sfd,0,0);
                        if(fdall[count]==-1)
                        {
                            printf("服務器崩潰!\n");
                            //釋放所有客戶
                            break;
                        }
                        printf("有客戶連接!\n");
                        count++;
                    }
                    //6.2.有客戶發送數據:客戶描述符號
                    for(i=0;i<count;i++)
                    {
                        //判定改變描述符號是否存在
                        if( fdall[i]!=-1 &&
                            FD_ISSET(fdall[i],&fds))
                        {
                            //讀取數據
                            r=recv(fdall[i],buf,1023,0);
                            if(r==0){
                                printf("有客戶退出!\n");
                                close(fdall[i]);
                                fdall[i]=-1;
                            }
                            if(r==-1){
                                printf("網絡故障!\n");
                                close(fdall[i]);
                                fdall[i]=-1;
                            }
                            if(r>0)
                            {
                                //廣播數據
                                buf[r]=0;
                                printf("廣播數據:%s\n",buf);
                                for(j=0;j<count;j++)
                                {
                                    if(fdall[j]!=-1)
                                    {
                                        send(fdall[j],buf,r,0);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            5.poll模式
              int poll(
                struct pollfd *fds,//監控的描述符號
                int nfds,//監控的描述符號的個數
                int timeout ); //阻塞超時

            #include <stdio.h>
            #include <fcntl.h>
            #include <signal.h>
            #include <unistd.h>
            #include <sys/poll.h>
            main()
            {    
                struct pollfd fds[1];
                int r;
                char buf[100];
                
                fds[0].fd=0;
                fds[0].events=POLLIN;
                while(1)
                {
                    
                    r=poll(fds,1,-1);
                    if(fds[0].revents & POLLIN)
                    {
                        printf("有數據輸入!\n");
                        r=read(0,buf,99);
                    }
                }
            }
            二.Socket選項設置
              1.socket有哪些選項可以設置
                 ARP
                  |
                 IP
                  |
              |-----------------|
              UDP            TCP     
              通用選項:
                SOL_SOCKET 
                  SO_BROADCAST  廣播
                  SO_RCVBUF    描述符號的緩沖的大小
                  SO_SNDBUF    描述符號的緩沖的大小
                  SO_REUSEADDR  地址反復綁定
                  SO_TYPE     描述符號類型SOCK_STREAM SOCK_DGRAM?
              ICMP選項
                IPPTOTO_ICMP
                  ICMP_FILTER
              IP選項(干預系統生成IP頭)
                IPPROTO_IP
                  ......
                  ......
              UDP選項
                IPPROTO_UDP
                  ......
              
              TCP選項    
                IPPROTO_TCP
                  ......      
              setsockopt設置選項
              getsockopt獲取選項
            案例:
              判定一個socket的數據類型AF_INET:SOCK_STREAM  SOCK_DGRAM SOCK_RAW

            #include <stdio.h>
            #include <sys/socket.h>
            #include <netinet/in.h>

            main()
            {
                int fd;
                int type;
                int len;
                len=sizeof(type);
                
                fd=socket(AF_INET,SOCK_DGRAM,0);
                
                getsockopt(fd,SOL_SOCKET,SO_TYPE,&type,&len);
                
                printf("%u:%u\n",SOCK_STREAM,type);
                if(type & SOCK_STREAM)
                {
                    printf("流!\n");
                }
                if(type & SOCK_DGRAM)
                {
                    printf("報文!\n");
                }
            }

            //獲得緩沖大小
            #include <stdio.h>
            #include <sys/socket.h>
            #include <netinet/in.h>

            main()
            {
                int fd;
                int type;
                int len;
                len=sizeof(type);
                
                fd=socket(AF_INET,SOCK_DGRAM,0);
                getsockopt(fd,SOL_SOCKET,SO_RCVBUF,&type,&len);  //在這里把參數SO_TYPE變成SO_RCVBUF即可
                printf("緩沖大小:%u\n",type);
            }
            案例:
              使用選項進行數據廣播.
              cast_A發送
                建立socket
                設置廣播選項
                發送數據(廣播方式發送)

            #include <stdio.h>
            #include <stdlib.h>
            #include <unistd.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>
            main()
            {
                int fd;
                int opt=1;
                int r;
                struct sockaddr_in dr;
                
                //1.選項設置
                fd=socket(PF_INET,SOCK_DGRAM,0);
                if(fd==-1) printf("1:%m\n"),exit(-1);
                
                r=setsockopt(fd,SOL_SOCKET,SO_BROADCAST,
                            &opt,sizeof(opt));
                if(r==-1) printf("2:%m\n"),exit(-1);
                dr.sin_family=AF_INET;
                dr.sin_port=htons(9999);
                //2.使用廣播IP地址
                dr.sin_addr.s_addr=inet_addr("192.168.180.255");
                
                r=sendto(fd,"Hello",5,0,
                    (struct sockaddr*)&dr,sizeof(dr));
                if(fd==-1) printf("3:%m\n");
                
                close(fd);
            }
              case_B接收
                建立socket
                設置地址可重用選項
                綁定地址
                接收數據 

            #include <stdio.h>
            #include <stdlib.h>
            #include <unistd.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>
            main()
            {
                int fd;
                int opt=1;
                char buf[100];
                int r;
                struct sockaddr_in dr;
                
                fd=socket(PF_INET,SOCK_DGRAM,0);
                if(fd==-1) printf("1:%m\n"),exit(-1);
                //1.選項
                r=setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,
                            &opt,sizeof(opt));
                if(r==-1) printf("2:%m\n"),exit(-1);
                
                dr.sin_family=AF_INET;
                dr.sin_port=htons(9999);
                //2.廣播地址
                dr.sin_addr.s_addr=inet_addr("192.168.180.255");
                
                r=bind(fd,(struct sockaddr*)&dr,sizeof(dr));
                if(r==-1) printf("3:%m\n"),exit(-1);
                
                r=recv(fd,buf,100,0);
                if(r>0)
                {
                    buf[r]=0;
                    printf("廣播數據:%s\n",buf);
                }
                close(fd);
                
            }
            三.OOB數據(TCP)  
              優先數據(帶外數據)
              send(,MSG_OOB);
              recv(,MSG_OOB);
            案例:
              oob_server.c
                 recv MSG_OOB
              oob_client.c 
                 send MSG_OOB 

            //oobServer
            #include <stdio.h>
            #include <stdlib.h>
            #include <unistd.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>
            #include <signal.h>
            #include <fcntl.h>
            int fd,cfd;
            void handle(int s)
            {

                char data[100];
                int r;
                if(s==SIGURG)
                {
                    r=recv(cfd,data,100,MSG_OOB);        
                
                    data[r]=0;
                    printf("$$%s\n",data);
                }
            }
            main()
            {
                
                int opt=1;
                char buf[100];
                int r;
                struct sockaddr_in dr;
                
                fd=socket(PF_INET,SOCK_STREAM,0);
                if(fd==-1) printf("1:%m\n"),exit(-1);
                printf("1\n");
                dr.sin_family=AF_INET;
                dr.sin_port=htons(10000);    
                dr.sin_addr.s_addr=inet_addr("192.168.180.92");
                
                r=bind(fd,(struct sockaddr*)&dr,sizeof(dr));
                if(r==-1) printf("2:%m\n"),exit(-1);
                printf("2\n");
                r=listen(fd,10);
                if(r==-1) printf("3:%m\n"),exit(-1);
                printf("3\n");
                signal(SIGURG,handle);
                cfd=accept(fd,0,0);
                fcntl(cfd,F_SETOWN,getpid());
                if(cfd==-1) printf("4:%m\n"),exit(-1);
                printf("4\n");
                while(1)
                {
                    r=recv(cfd,buf,100,0);
                    if(r>0)
                    {
                        buf[r]=0;
                        printf("接收數據:%s\n",buf);
                    }        
                    else
                    {
                        break;
                    }        
                }
                close(cfd);
                close(fd);
                
            }

            //oobClient
            #include <stdio.h>
            #include <stdlib.h>
            #include <unistd.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>
            main()
            {
                int fd;
                int opt=1;
                char buf[100];
                int r;
                struct sockaddr_in dr;
                fd_set fds;
                
                fd=socket(PF_INET,SOCK_STREAM,0);
                if(fd==-1) printf("1:%m\n"),exit(-1);
                printf("1\n");
                dr.sin_family=AF_INET;
                dr.sin_port=htons(10000);    
                dr.sin_addr.s_addr=inet_addr("192.168.180.92");
                
                r=connect(fd,(struct sockaddr*)&dr,sizeof(dr));
                if(r==-1) printf("2:%m\n"),exit(-1);    
                while(1)
                {
                    FD_ZERO(&fds);
                    FD_SET(fd,&fds);
                    select(fd+1,0,&fds,0,0);
                    send(fd,"Hello",5,MSG_OOB);        
                }
                close(fd);
                
            }

            OOB總結:
              1.OOB數據只能一個字符
              2.普通數據使用一般方式接收與發送,OOB數據使用MSG_OOB接收與發送
              3.一個數據使用MSG_OOB,則最后一個是OOB,其他非OOB數據
              4.問題:OOB數據是優先數據。優先體現在什么地方? 接收OOB數據的時候,會產生一個URG信號

            四.HTTP協議以及應用            
             1.HTTP協議版本HTTP1.0 HTTP1.1 
             2.HTTP是應用協議
             3.HTTP協議分成:
                請求協議
                響應協議
             4.請求協議的格式:
               請求行(請求方法 請求資源 協議版本)  
               請求體(請求頭:請求值)
               空行
               數據(querystring:key=value&key=value) 


            #include <stdio.h>
            #include <stdlib.h>
            #include <string.h>
            #include <unistd.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>

            main()
            {
                int fd;
                struct sockaddr_in dr;
                char strreq[1024];
                char buf[10*1024];
                int r; 
                //建立socket
                fd=socket(AF_INET,SOCK_STREAM,0);
                
                //連接服務器192.168.0.72
                dr.sin_family=AF_INET;
                dr.sin_port=htons(80);
                dr.sin_addr.s_addr=inet_addr("192.168.0.72");
                r=connect(fd,(struct sockaddr*)&dr,sizeof(dr));

                
                //構建http請求字符串
                sprintf(strreq,
                    "GET /index.php HTTP/1.1\r\n"
                    "Host: 192.168.0.72:80\r\n"
                    "User-Agent: Tarena5.0\r\n"
                    "Accept: text/html,image/png\r\n"
                    "Accept-Language: zh-cn\r\n"
                    "Accept-Charset: gb2312,utf-8\r\n"
                    "Keep-Alive: 300\r\n"
                    "Connection: keep-alive\r\n"
                    "\r\n");
                //發送http請求字符串
                r=send(fd,strreq,strlen(strreq),0);
                //等待服務器響應
                
            //while(1)
                
            //{
                    r=recv(fd,buf,1024,0);
                    //if(r<=0) break;
                    printf("========================\n");
                    printf("%s\n",buf);
                    printf("========================\n");
                //}
                close(fd);
            }

             5.響應協議的格式
               響應行(協議版本 響應碼 響應碼的文本描述)
               響應體(響應頭: 響應值)
               空行
               數據(普通數據/分塊數據)

             響應碼:    
               1XX  正在處理
               2XX  響應成功(200表示完全成功)
               3XX  繼續處理
               4XX  客戶錯誤
               5XX  服務器錯誤


            #include <stdio.h>
            #include <stdlib.h>
            #include <unistd.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>
            #include <signal.h>
            #include <fcntl.h>
            #include <string.h>
            int fd,cfd;
            main()
            {
                char buf[1024];
                int r;
                struct sockaddr_in dr;
                char strres[1024];
                
                fd=socket(PF_INET,SOCK_STREAM,0);
                if(fd==-1) printf("1:%m\n"),exit(-1);
                printf("1\n");
                dr.sin_family=AF_INET;
                dr.sin_port=htons(10000);    
                dr.sin_addr.s_addr=inet_addr("192.168.180.92");
                
                r=bind(fd,(struct sockaddr*)&dr,sizeof(dr));
                if(r==-1) printf("2:%m\n"),exit(-1);
                printf("2\n");
                r=listen(fd,10);
                if(r==-1) printf("3:%m\n"),exit(-1);
                printf("3\n");    
                cfd=accept(fd,0,0);    
                if(cfd==-1) printf("4:%m\n"),exit(-1);
                printf("4\n");
                sprintf(strres,
                    "HTTP/1.1 200 OK\r\n"
                    "Server: tarena2.0\r\n"
                    "Content-Type: text/html\r\n"
                    "Content-Length: 28\r\n"
                    "Connection: keep-alive\r\n"
                    "\r\n"
                    "<font color=red>靚崽!</font>");
                while(1)
                {
                    r=recv(cfd,buf,1024,0);
                    if(r>0)
                    {
                        buf[r]=0;
                        printf("接收數據:%s\n",buf);
                        send(cfd,strres,strlen(strres),0);
                    }        
                    else
                    {
                        break;
                    }
                            
                }    
                close(cfd);
                close(fd);
            }

            五.ioctl函數
              實現ifconfig工具

            總結:
              重點:
                select
                廣播

              了解:
                OOB數據
                HTTP協議

              應用:
                獨立編寫TCP服務器端的select模式
                編寫廣播
                能夠請求一個網頁,并且解析響應
            作業:
              1.把聊天程序使用poll實現
              2.使用UDP的廣播,發送一個文件    
              3.隨意挑選網站,把主頁下載并保存成html文件

            久久丫精品国产亚洲av不卡| 中文字幕无码精品亚洲资源网久久| 久久国产欧美日韩精品免费| 99久久久国产精品免费无卡顿 | 久久精品国产亚洲网站| 亚洲AV日韩精品久久久久久久 | 麻豆久久久9性大片| 久久综合成人网| 一本色道久久HEZYO无码| 99精品国产在热久久无毒不卡| 亚洲午夜久久久久久久久电影网| 99久久夜色精品国产网站| 中文精品久久久久人妻不卡| 无码任你躁久久久久久久| 国产69精品久久久久9999APGF | 久久国产色AV免费观看| 蜜桃麻豆www久久| 久久久久av无码免费网| 久久综合香蕉国产蜜臀AV| 亚洲AV无一区二区三区久久| 久久AV高潮AV无码AV| 国产精品欧美久久久天天影视| 亚洲国产成人久久精品影视| 亚洲国产二区三区久久| 天天影视色香欲综合久久| 无码国产69精品久久久久网站| 久久精品人人做人人爽电影| 久久久久夜夜夜精品国产| 一本色道久久88综合日韩精品 | 久久无码中文字幕东京热| 久久精品人人做人人爽电影| 精品国产乱码久久久久久浪潮| 精品精品国产自在久久高清| 国内精品久久国产大陆| 久久精品国产亚洲综合色| 国产午夜福利精品久久| 思思久久精品在热线热| 777午夜精品久久av蜜臀| 色偷偷久久一区二区三区| 精品久久久久久久中文字幕 | 精品无码久久久久久久动漫|