• <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
            struct  sembuf 
            {
                int sem_num;//下標
                int sem_op;
                int sem_flg;//建議為0.
            }一.信號量(同步)
             1.回顧:
               一個進程控制另外一個進程.
               邏輯變量+pause/sleep+信號
             2.信號量(semaphore)信號燈
              三個數據:紅燈/綠燈/黃燈    
                    60   90   10
              信號量是共享內存整數數組.根據需要定義指定的數組長度
              信號量就是根據數組中的值,決定阻塞還是解除阻塞
             
             3.編程
               3.1.創建或者得到信號量     semget
               3.2.初始化信號量中指定下標的值 semctl
               3.3.根據信號量阻塞或者解除阻塞 semop
               3.4.刪除信號量         semctl
            案例:
               A:             B
               創建信號量        得到信號量
               初始化信號量      
               根據信號量阻塞     解除阻塞
               刪除信號量       
                
               semget函數說明
            int semget(key_t key,
                    int nums,//信號量數組個數
                    int flags);//信號量的創建標記
                                            
            //創建IPC_CREAT|IPC_EXCL|0666
                                            
            //打開0
              返回:  -1:失敗
                  >=0:成功返回信號量的ID
            int semop(
                    int semid,//信號量ID
                    struct sembuf *op,//對信號量的操作.操作可以是數組多個
                    size_t nums,//第二個參數的個數
                );
              返回:
                 -1:時失敗
                  0:成功 
            int semctl(int semid,
                        int nums,//對IPC_RMID無意義
                        int cmd,//SETVAL  IPC_RMID
                        );//對IPC_RMID無意義
              sem_op:
                 前提條件信號量是unsigned short int;
                 不能<0.
                 -:夠減,則semop馬上返回,不夠減,則阻塞.
                 +:執行+操作
                 0:判定信號量>0,則阻塞,直到為0
               控制進程的搭配方式:
                  +(解除阻塞) -(阻塞)
                  0(阻塞)     -(解除阻塞)
            #include <stdio.h>
            #include <unistd.h>
            #include <stdlib.h>
            #include <sys/ipc.h>
            #include <sys/sem.h>
            //2.1.定義一個聯合體
            union semun {
                int    val;
                struct semid_ds *buf;
                unsigned short  *array;
                struct seminfo  *__buf;
            };

            main()
            {
                key_t key;
                int semid;    //信號量ID
                union  semun v;//2.2.定義初始化值
                int r;
                struct sembuf op[1];
                //1.創建信號量
                key=ftok(".",99);
                if(key==-1) printf("ftok err:%m\n"),exit(-1);
                
                //semid=semget(key,1/*信號量數組個數*/,
                
            //        IPC_CREAT|IPC_EXCL|0666);
                        
                semid=semget(key,1,0);//得到信號量
                if(semid==-1) printf("get err:%m\n"),exit(-1);
                
                printf("id:%d\n",semid);
                //2.初始化信號量
                v.val=2;
                r=semctl(semid,0,SETVAL,v);//2.3設置信號量的值
                if(r==-1) printf("初始化失敗!\n"),exit(-1);

                //3.對信號量進行阻塞操作
                
            //3.1.定義操作
                op[0].sem_num=0;//信號量下標
                op[0].sem_op=-1;//信號量操作單位與類型
                op[0].sem_flg=0;
                while(1)
                {
                    r=semop(semid,op,1);
                    printf("解除阻塞!\n");
                }
                
                //4.刪除(可以不刪除)
            }

            #include <stdio.h>
            #include <unistd.h>
            #include <stdlib.h>
            #include <sys/ipc.h>
            #include <sys/sem.h>
            //2.1.定義一個聯合體
            union semun {
                int    val;
                struct semid_ds *buf;
                unsigned short  *array;
                struct seminfo  *__buf;
            };

            main()
            {
                key_t key;
                int semid;    //信號量ID
                union  semun v;//2.2.定義初始化值
                int r;
                struct sembuf op[2];
                //1.創建信號量
                key=ftok(".",99);
                if(key==-1) printf("ftok err:%m\n"),exit(-1);
                
                        
                semid=semget(key,1,0);//得到信號量
                if(semid==-1) printf("get err:%m\n"),exit(-1);
                
                printf("id:%d\n",semid);        
                //3.對信號量進行阻塞操作
                
            //3.1.定義操作
                op[0].sem_num=0;//信號量下標
                op[0].sem_op=1;//信號量操作單位與類型
                op[0].sem_flg=0;
                op[1].sem_num=0;//信號量下標
                op[1].sem_op=1;//信號量操作單位與類型
                op[1].sem_flg=0;
                while(1)
                {
                    r=semop(semid,op,2);
                    sleep(1);
                }
                
                //4.刪除(可以不刪除)
                
            //semctl(semid,0,IPC_RMID);
            }

            二.網絡
             1.基礎(ip)
              1.1.網絡工具
                ping
                ping ip地址
                ping -b ip廣播地址
                ifconfig -a    
                
                netstat -a
                netstat -u
                netstat -t
                netstat -x
                netstat -n
                
                route
                lsof
              1.2.網絡的基本概念
                網絡編程采用socket模型.
                網絡通信本質也是進程之間的IPC。
                   是不同主機之間。
                
                識別主機:4字節整數:IP地址
                識別進程:2字節整數:端口號
                  
                IP地址的表示方法: 內部表示:4字節整數 
                           外部表示:數點字符串
                                結構體
                  1 2 3 4  分段表示,每個段使用.分割
                  "192.168.0.26"

                ip地址的轉換:  

            struct  sockaddr_in
                {
                    int                         sin_family;
                    in_port_t             sin_port;
                    struct in_addr     sin_addr;
                    
                }
             struct in_addr
                {
                    in_addr_t  s_addr;
                }    
               //總結:
                  IP地址的表示
                    字符串表示"192.168.0.26"
                    整數表示:in_addr_t;
                    字結構表示struct in_addr;
                  連接點:endpoint
             struct sockaddr_in
                {
                    in_port_t                 sin_port;
                    struct in_addr       sin_addr;
                };
             1.3.IP地址的轉換
               inet_addr   //把字符串IP轉換為二進制整數IP(網絡字節序)
               inet_aton  //把字符串IP轉換為struct in_addr;(網絡字結序) 
               #inet_network//把字符串IP轉換為二進制整數IP(本地字節序)
               inet_ntoa  //把結構體struct in_addr轉換為字符串IP
               
              4個本地主機字節序與網絡序轉換函數:
              h表示主機字節序,n表示網絡字節序,s表示兩個2字節,l表示4個字節
               uint16_t htons(uint16_t)
               uint32_t htonl(uint32_t)
               uint16_t ntohs(uint16_t)
               uint32_t ntohl(uint32_t)
               ps:所以發送時候,端口轉換可以用htons,而ip可以用htonl

            #include <stdio.h>
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>
            main()
            {
                /*
                in_addr_t  nip=192<<24 | 168 <<16 | 0<<8  | 26;
                char  *ip="192.168.0.26";
                //把整數轉換為字符串inet_ntoa
                struct in_addr sip;
                int myip;
                
                sip.s_addr=nip;
                
                printf("nip:%u\n",nip);
                
                printf("%s\n",inet_ntoa(sip));
                
                myip=inet_addr(ip);
                printf("%u\n",myip);
                
                printf("%hhu.%hhu.%hhu.%hhu\n",    myip>>24 & 255,
                                        myip>>16 & 255,
                                        myip>>8  & 255,
                                        myip>>0  & 255);
                
            */
                /*
                char ip[4]={192,168,0,26};
                printf("%d\n",*(int*)ip);
                
            */
                char *ip="10.45.8.1";
                struct in_addr addr;
                in_addr_t net;
                in_addr_t host;
                struct in_addr tmp;
                
                inet_aton(ip,&addr);
                net=inet_lnaof(addr);
                host=inet_netof(addr);
                
                tmp.s_addr=net;
                
                printf("%s\n",inet_ntoa(tmp));
                
                tmp.s_addr=host;
                printf("%s\n",inet_ntoa(tmp));
            }
            1.4.IP地址的意義 
               IP地址的位表達不同意義:
                 IP地址組建網絡:網絡標識/主機標識
                      網絡     主機
               A類     7         24    網絡少  主機
               B類     14         16      
               C類     21          8 
               D類     組播 
               E類     沒有使用
               
              1.5.計算機系統中的網絡配置
               /etc/hosts文件  配置IP,域名,主機名
                  gethostbyname
                  gethostbyaddr
               /etc/protocols文件  配置系統支持的協議
               /etc/services文件 配置服務   
               get***by***;   
               gethostbyname   
               getprotobyname

            #include <stdio.h>
            #include <netdb.h>
            main()
            {
                struct hostent *ent;
                /*打開主機配置數據庫文件*/
                sethostent(1);
                while(1)
                {
                    ent=gethostent();
                    if(ent==0) break;
                    
                    printf("主機名:%s\t",ent->h_name);
                    printf("IP地址:%hhu.%hhu.%hhu.%hhu\t",
                            ent->h_addr[0],
                            ent->h_addr[1],
                            ent->h_addr[2],
                            ent->h_addr[3]);
                    printf("別名:%s\n",ent->h_aliases[0]);
                }
                endhostent();
            }

            #include <stdio.h>
            #include <netdb.h>
            main()
            {
                struct hostent *ent;
                ent=gethostbyname("bbs.tarena.com.cn");
                //printf("%s\n",ent->h_aliases[0]);
                printf("%hhu.%hhu.%hhu.%hhu\n",
                    ent->h_addr_list[0][0],
                    ent->h_addr_list[0][1],
                    ent->h_addr_list[0][2],
                    ent->h_addr_list[0][3]);
            }

            #include <stdio.h>
            #include <netdb.h>
            #include <sys/utsname.h>
            main()
            {
                struct protoent *ent;
                struct utsname name;
                ent=getprotobyname("tcp");
                printf("%d\n",ent->p_proto);
                
                uname(&name);
                printf("%s\n",name.machine);
                printf("%s\n",name.nodename);
                printf("%s\n",name.sysname);
                printf("%s\n",name.domainname);
            }
            2.TCP/UDP編程
               對等模型:AF_INET   SOCK_DGRAM    0:UDP
               C/S 模型:AF_INET  SOCK_STREAM   0:TCP
              2.0.網絡編程
                ISO的7層模型:
                   物理層     
                   數據鏈路層   數據鏈路層(數據物理怎么傳輸)
                   網絡層     IP層   (數據的傳輸方式)
                   傳輸層     傳輸層   (數據傳輸的結果)     
                   會話層     應用層   (數據傳遞的含義)
                   表示層
                   應用層
                     
              2.1.UDP編程的數據特點
                UDP采用對等模型SOCK_DGRAM
                socket            socket:socket
                綁定IP地址bind        連接目標(可選)  conncect
                read/recv/recvfrom      發送數據 write/send/sendto
                關閉close   
            案例:
              A:                    B
               接收用戶的數據         發送數據
               打印數據與發送者IP     接收數據并打印
               返發一個信息       

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

            main()
            {
                int fd;//socket描述符號
                struct sockaddr_in ad;//本機的IP地址
                char buf[100];//接收數據緩沖
                
                struct sockaddr_in ad_snd;//發送者IP地址
                socklen_t len;//發送者IP的長度
                int r;
                
                fd=socket(AF_INET,SOCK_DGRAM,17);
                if(fd==-1) printf("socket:%m\n"),exit(-1);
                printf("建立socket成功!\n");
                
                ad.sin_family=AF_INET;
                ad.sin_port=htons(11111);
                inet_aton("192.168.180.92",&ad.sin_addr);
                r=bind(fd,(struct sockaddr*)&ad,sizeof(ad));
                if(r==-1) printf("bind err:%m\n"),exit(-1);
                printf("綁定成功!\n");
                
                while(1)
                {
                    len=sizeof(ad_snd);
                    r=recvfrom(fd,buf,sizeof(buf)-1,0,
                            (struct sockaddr*)&ad_snd,&len);
                    if(r>0){
                        buf[r]=0;
                        printf("發送者IP:%s,端口:%hu,數據:%s\n",
                            inet_ntoa(ad_snd.sin_addr),
                            ntohs(ad_snd.sin_port),buf);
                        sendto(fd,"古怪!",strlen("古怪!"),0,
                        (struct sockaddr*)&ad_snd,sizeof(ad_snd));
                    }
                    if(r==0)
                    {
                        printf("關閉!\n");            
                        break;
                    }
                    if(r==-1)
                    {
                        printf("網絡故障!\n");            
                        break;
                    }
                }
                
                close(fd);
            }
             總結:
                1.問題:
                  connect + send  == sendto
                2.問題:
                  recvfrom的作用不是專門從指定IP接收
                  而是從任意IP接收數據,返回發送數據者的IP
                3.問題:
                  為什么要bind,bind主要目的告訴網絡發送數據的目標.
                  是否一定綁定才能發送數據?
                  否:只要知道你的IP與PORT,就能發送數據.
                4.問題:
                  為什么發送者沒有綁定IP與端口,他也有端口?
                  底層網絡驅動,幫我們自動生成IP與端口.
                5.缺陷:
                  接收方不區分發送者的.  
                    
             send函數  
             sendto函數
            int sendto(
                    int fd,//socket描述符號
                    const void *buf,//發送的數據緩沖
                    size_t size,//發送的數據長度
                    int flags,//發送方式MSG_NOWAIT MSG_OOB
                    const struct sockaddr *addr,//發送的目標的IP與端口
                    socklen_t len//sockaddr_in的長度
                );
               返回:
                 -1:發送失敗
                 >=0:發送的數據長度
             recv函數
             recvfrom函數 
            int recvfrom(
                    int fd,
                    void *buf,
                    size_t size,
                    int flags,
                    struct sockaddr*addr,//返回發送者IP與端口
                    socklen_t *len);//輸入返回IP的緩沖大小,返回實際IP的大小
             2.2.TCP編程的數據特點
              2.3.TCP服務器的編程
             3.TCP的服務器編程模型
             4.IP協議與處理(SOCK_RAW,SOCK_PACKET)
             5.pcap編程
             6.HTTP協議與網頁搜索
             
            作業:
              1.重新編寫UDP網絡通信 
              2.使用gethostbyname的得到bbs.tarena.com.cn
            亚洲综合日韩久久成人AV| 久久人人爽人人爽人人AV| 久久无码人妻一区二区三区| 一极黄色视频久久网站| 久久久精品人妻无码专区不卡 | 久久精品无码免费不卡| 国产ww久久久久久久久久| 国产午夜电影久久| 久久久久九九精品影院| 亚洲性久久久影院| 亚洲日韩中文无码久久| 欧美噜噜久久久XXX| 国产精品欧美久久久天天影视 | 精品久久久久久无码中文字幕| 四虎国产永久免费久久| 久久久久无码中| 久久精品成人欧美大片| 久久精品国产亚洲77777| 久久久精品免费国产四虎| 久久91这里精品国产2020| 午夜精品久久久内射近拍高清| 精品久久久无码人妻中文字幕| 亚洲AV无码久久精品色欲| 国内精品久久久久影院免费| 国产精品久久久久久久午夜片| 久久天天躁狠狠躁夜夜不卡| 久久天天躁狠狠躁夜夜2020一| 久久天天躁狠狠躁夜夜avapp| 久久精品这里热有精品| 精品国产日韩久久亚洲| 1000部精品久久久久久久久| 91精品国产91久久| 国内精品九九久久精品| 国产精品热久久无码av| 97久久国产露脸精品国产 | 精品无码人妻久久久久久 | 99久久国产综合精品麻豆| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 97久久国产亚洲精品超碰热| 久久久久亚洲AV成人网人人网站 | 日韩av无码久久精品免费|