青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 200, comments - 8, trackbacks - 0, articles - 0
一.TCP的編程模型
 回顧:
  UDP模型的UML圖
  TCP模型的UML圖
 案例1:
  TCP的服務器(在案例中使用瀏覽器作為客戶程序)  
 socket建立服務器的文件描述符號緩沖
 bind把IP地址與端口設置到文件描述符號中
 listen負責根據客戶連接的不同IP與端口,負責生成對應的文件描述符號及其信息
 accept一旦listen有新的描述符號產生就返回,否則阻塞。 

//tcpserver.c
#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 serverfd;
    int cfd;
    int a;
    struct sockaddr_in sadr;
    struct sockaddr_in cadr;
    socklen_t len;
    int r;
    char buf[1024];
    //1.socket
    serverfd=socket(AF_INET,SOCK_STREAM,0);
    if(serverfd==-1) printf("1:%m\n"),exit(-1);
    printf("建立服務器socket成功!\n");
    //2.bind
    sadr.sin_family=AF_INET;
    sadr.sin_port=htons(9999);
    inet_aton("192.168.180.92",&sadr.sin_addr);
    r=bind(serverfd,
            (struct sockaddr*)&sadr,sizeof(sadr));
    if(r==-1) printf("2:%m\n"),exit(-1);
    printf("服務器地址綁定成功!\n");
    
    //3.listen
    r=listen(serverfd,10);
    if(r==-1) printf("3:%m\n"),exit(-1);
    printf("監聽服務器成功!\n");
    
    //4.accept
    len=sizeof(cadr);
    cfd=accept(serverfd,
            (struct sockaddr*)&cadr,&len); //每接受一個新的連接,就會返回一個新的文件描述符,來分辨是哪個連接。
    printf("有人連接:%d,IP:%s:%u\n",
            cfd,inet_ntoa(cadr.sin_addr),
            ntohs(cadr.sin_port));        
    
    //5.處理代理客戶描述符號的數據
    while(1)
    {
        r=recv(cfd,&a,4,MSG_WAITALL);        
        if(r>0)
        {
            //buf[r]=0;
            printf("::%d\n",a);
        }
        
        if(r==0)
        {
            printf("連接斷開!\n");
            break;
        }
        if(r==-1)
        {
            printf("網絡故障!\n");
            break;
        }
    }
    close(cfd);
    close(serverfd);
}

案例2:
   每個客戶的代理描述符號的通信

二.TCP通信特點(相對于UDP)
 案例3:
  有連接:主要連接后,發送數據不用指定IP與端口
  數據無邊界:TCP數據流,非數據報文.
  描述符號雙工:
  數據準確:TCP協議保證數據時完全正確
 案例4:
  使用TCP發送數據注意:
    不要以為固定長的數據,一定接收正確,要求使用MSG_WAITALL(必須等待得到指定緩存長度recv才返回)
  
 案例5:
  TCP數據發送的分析:
    定長數據:
      基本數據int short long float  double
      結構體數據struct
      建議使用MSG_WAITALL
    
    不定長數據:
      字符串數據以及文件數據等不固定長度的數據怎么發送?   
      制定數據包:
        頭:大小固定(數據大小)
        體:大小變化(數據)  
 案例6:
   使用TCP傳送文件
   定義文件數據包.
     int 數據大小;
     char[]數據
       
   傳遞文件名
   傳遞數據(循環)
   傳遞0長度的數據表示文件結束
代碼如下:


//demo1Client.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 <fcntl.h>
main()
{
    //1. 建立socket
    
//2. 連接到服務器
    
//3. 打開文件
    
//4. 發送文件名
    
//5. 循環發送文件
    
//6. 讀取到文件尾,發送0數據包
    int sfd; //socket描述符
    int ffd; //文件描述符
    int size;   //讀取和發送文件的長度
    int r;  //函數返回值
    
    int  len;  //要發送的文件名的長度
    char buf[128]; //數據的緩存
    
    struct sockaddr_in dr;  //網絡地址
    char filename[]="udp_a.c";  //文件名
    
    
//1.建立socket
    sfd=socket(AF_INET,SOCK_STREAM,0);
    if(sfd==-1) 
        printf("1:%m\n"),exit(-1);
    printf("socket成功!\n");
    //2.連接到服務器
    dr.sin_family=AF_INET;
    dr.sin_port=htons(9988);
    inet_aton("192.168.180.92",&dr.sin_addr);
    r=connect(sfd,(struct sockaddr*)&dr,sizeof(dr));
    if(r==-1) 
        printf("2:%m\n"),close(sfd),exit(-1);    
    printf("connect成功!\n");
    //3.打開文件
    ffd=open(filename,O_RDONLY);
    if(ffd==-1) 
        printf("3:%m\n"),close(sfd),exit(-1);
    printf("open文件成功!\n");
    //4.發送文件名
    len=strlen(filename);    
    r=send(sfd,&len,sizeof(len),0);//發送文件名長度(告訴流,文件名占多長)
    r=send(sfd,filename,len,0);//發送文件名 
    if(r==-1)
    printf("4:%m\n"),close(ffd),close(sfd),exit(-1);
    printf("發送文件名成功!\n");
    //5.循環發送數據
    while(1)
    {
        size=read(ffd,buf,128);
        if(size==-1) break//read錯誤,跳出循環
        if(size==0) break;  //讀到文件尾,跳出循環
        if(size>0)
        {
            //先發送數據的長度,再發送數據
            
//發送數據長度
            r=send(sfd,&size,sizeof(size),0);
            if(r==-1) break;
            r=send(sfd,buf,size,0);//發送數據
            if(r==-1) break;
        }
    }
    //6.讀取到文件尾,發送0數據包
    size=0;
    r=send(sfd,&size,sizeof(size),0);
    close(ffd);
    close(sfd);
    printf("OK!\n");
}

//demo1server.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 <fcntl.h>
main()
{
    //1. 建立服務器socket
    
//2. 綁定IP地址與端口
    
//3. 監聽
    
//4. 接收連接
    
//5. 接收文件名
    
//6. 創建文件
    
//7. 循環接收文件數據
    
    int sfd, cfd, ffd;
    int r;
    int len;
    char buf[128];  //發送端定義的緩存大小是128,這里最好不要小于128
    char filename[100];
    struct sockaddr_in dr;
    //1. 建立服務器socket
    sfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd == -1)
        printf("1:%m\n"), exit(-1);
    printf("socket服務器創建成功!\n");
    //2. 綁定IP地址與端口
    dr.sin_family = AF_INET;
    dr.sin_port = htons(9988);
    inet_aton("192.168.180.92", &dr.sin_addr); //dr.sin_addr.s_addr = inet_addr("192.168.180.92");注意區別
    r = bind(sfd, (struct sockaddr*)&dr, sizeof(dr));
    if(r == -1)
        printf("2:%m"), close(sfd), exit(-1);
    printf("綁定地址成功!\n");
    //3. 監聽
    r = listen(sfd, 10);
    if(r == -1)
        printf("3:%m\n"), close(sfd), exit(-1);
    printf("監聽成功!\n");
    //4. 接收連接
    cfd = accept(sfd, 0, 0); //這里我們不關心發送端的IP等信息,所以后面兩個參數都為0。這里返回一個新的描述符,代表接收的連接
    if(cfd == -1)
        printf("4:%m\n"), close(sfd), exit(-1);
    printf("開始接收文件!\n");
    //5. 接收文件名
    r = recv(cfd, &len, sizeof(len), MSG_WAITALL);  //接收文件名的長度
    r = recv(cfd, filename, len, MSG_WAITALL);  //根據文件名長度,接收文件名
    filename[r] = 0;  //在文件名后面加結束符
    
//6. 創建文件
    ffd = open(filename, O_CREAT|O_RDWR, 0666);   //如果文件存在,直接覆蓋.不要和發送文件放在同一個目錄運行,會覆蓋發送文件
    if(ffd == -1)
        printf("6:%m\n"), close(sfd), close(cfd), exit(-1);
    printf("創建文件成功!\n");
    //7. 循環接收文件數據
    while(1)
    {
        r = recv(cfd, &len, sizeof(len), MSG_WAITALL);
        if(len == 0)
            break//長度為0,表示文件傳送完畢的信號
        r = recv(cfd, buf, len, MGS_WAITALL);
        r = write(ffd, buf, len);
    }
    close(ffd);
    close(cfd);
    close(sfd);
    printf("接收數據完畢!\n");
}

PS:UDP面向無連接,TCP面向連接,所以推薦UDP不用connect,直接sendto, 而TCP則先連接,然后send,而不是sendto。

三.TCP服務器編程模式
  TCP的服務器端維護多個客戶的網絡文件描述符號.
  對服務器多個客戶描述符號同時做讀操作,是不可能.需要多任務模型完成.
  多任務模型?
  1.多進程
  2.IO的異步模式(select模式/poll模式)
  3.多線程模式  
  4.多進程池
  5.線程池

四.綜合應用--多進程應用
  1.怎樣使用多進程
  2.多進程的缺陷,以及怎么解決

小例子:用TCP寫一個聊天程序
   客戶端
     2.1.建立socket
     2.2.連接服務器
     2.3.創建CURSES界面
     2.4.創建子進程
     2.5.在父進程中,輸入,發送聊天信息
     2.6.在子進程中,接收服務器傳遞其他客戶聊天信息


//chatclient.c
//聊天程序客戶端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <curses.h>
#include <signal.h>
WINDOW*winfo,*wmsg;
int fd;
int r;
struct sockaddr_in dr;
int isover=1;

int initSocket();   //初始化:創建描述符,綁定IP
void initUI();   //初始化curses界面
void destroy();  //清理:釋放UI, 關閉網絡
void handle(int s)
{
    int status;
    wait(&status);
    destroy();
    exit(-1);    
}
main()
{    
    //printf("網絡初始化成功!\n");
    initUI();
    r=initSocket();    
    if(r==-1) exit(-1);
    signal(SIGCHLD,handle);
    if(fork())
    {
        //父進程,輸入,發送
        char buf[256];
        while(1)
        {
            mvwgetstr(wmsg,1,1,buf);
            //buf[r]=0;
            send(fd,buf,strlen(buf),0);            
            //wclear(wmsg);
            
//box(wmsg,0,0);
            refresh();
            wrefresh(wmsg);
            wrefresh(winfo);
        }
    }
    else
    {
        
        //子進程,接收,顯示
        char buf[256];
        int line=1;
        while(1)
        {            
            r=recv(fd,buf,255,0);
            if(r==-1) break;
            if(r==0) break;
            buf[r]=0;
            mvwaddstr(winfo,line,1,buf);
            line++;            
            if(line>=(LINES-3))
            {
                wclear(winfo);
                line=1;
                box(winfo,0,0);                
            }
            
            
            wmove(wmsg,1,1);
            touchwin(wmsg);
            refresh();
            wrefresh(winfo);            
            wrefresh(wmsg);
        }
        exit(-1);
    }
        
    destroy();
}
void destroy()
{
    close(fd);
    endwin();
}
void initUI()
{
    initscr();
    winfo=derwin(stdscr,(LINES-3),COLS,0,0);
    wmsg=derwin(stdscr,3,COLS,LINES-3,0);
    keypad(stdscr,TRUE);
    keypad(wmsg,TRUE);
    keypad(winfo,TRUE);
    box(winfo,0,0);
    box(wmsg,0,0);
    refresh();
    wrefresh(winfo);
    wrefresh(wmsg);
}

int initSocket()
{
    fd=socket(AF_INET,SOCK_STREAM,0);
    if(fd==-1) return -1;
        
    dr.sin_family=AF_INET;
    dr.sin_port=htons(9989);
    dr.sin_addr.s_addr=inet_addr("192.168.180.92");
    r=connect(fd,(struct sockaddr*)&dr,sizeof(dr));
    if(r==-1)
    {
        close(fd);
        return -1;
    }
    return 0;  //fd是全局變量,不用返回。初始化成功,返回0
}

//chatserver.c
//聊天程序服務器端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/mman.h>
int sfd;
int *fds;//存放所有客戶代理描述符號
int idx=0;//客戶在數組中下標
struct sockaddr_in dr;
int r;
main()
{
    //1. 建立服務器socket
    
//2. 綁定地址
    
//3. 監聽
    
//4. 循環接收客戶連接
    
//5. 建立一個子進程
    
//6. 子進程任務:接收客戶數據并且廣播
    
    
    
//1.建立服務器 socket
    fds=mmap(0,4*100,PROT_READ|PROT_WRITE,
        MAP_ANONYMOUS|MAP_SHARED,0,0);
    bzero(fds,sizeof(fds));
    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(9989);
    dr.sin_addr.s_addr=inet_addr("192.168.180.92");
    r=bind(sfd,(struct sockaddr*)&dr,sizeof(dr));
    if(r==-1) printf("2:%m\n"),exit(-1);
    printf("bind ok!\n");
    //3.監聽
    r=listen(sfd,10);
    if(r==-1) printf("3:%m\n"),exit(-1);
    printf("listen ok!\n");
    //4.循環接收客戶連接
    while(1)
    {
        fds[idx]=accept(sfd,0,0);
        if(fds[idx]==-1) break;
        printf("有客戶連接:%d\n",fds[idx]);
        //5.建立一個子進程
        if(fork())
        {
            idx++;
            continue;
        }
        else
        {        
            //6.子進程任務:接收客戶數據并且廣播
            char buf[256];
            int i;
            printf("開始接收客戶數據:%d\n",fds[idx]);
            while(1)
            {
                //接收客戶數據
                r=recv(fds[idx],buf,255,0);
                printf("%d\n",r);
                if(r==0)
                {
                    printf("有客戶退出\n");
                    close(fds[idx]);
                    fds[idx]=0;
                    break;                    
                }
                if(r==-1)
                {
                    printf("網絡故障\n");
                    close(fds[idx]);
                    fds[idx]=0;
                    break;
                }
                buf[r]=0;
                printf("來自客戶的數據:%s\n",buf);
                //廣播
                for(i=0;i<100;i++)
                {
                    if(fds[i]>0)
                    {
                        send(fds[i],buf,r,0);
                    }    
                }
            }
            exit(0);
        }
    }
    close(sfd);    
}

總結:
   建立socket
   綁定地址
   監聽
   循環接收客戶連接
   為客戶創建子進程
   在子進程接收該客戶的數據,并且廣播

總結:
  1.TCP的四大特點
  2.TCP的數據接收:固定長與變長數據的接收
  3.TCP的服務器多進程處理
     問題:多進程由于進程資源結構獨立.
         新進程的文件描述符號的環境在老進程無法訪問?

作業:
  思考:
    有什么編程技巧可以解決進程的文件描述符號的一致?
    
  作業:
    完成TCP的聊天程序.
      1.數據能運行
      2.處理僵死進程
      3.服務器退出,客戶也能正常結束
      4.客戶退出,服務器也能夠正確結束客戶連接.

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            99热精品在线观看| 亚洲一区二区免费在线| 久久精品最新地址| 99re成人精品视频| 亚洲激情av在线| 久久久人人人| 欧美在线免费看| 性欧美videos另类喷潮| 在线亚洲免费视频| 国产精品99久久久久久久女警 | 欧美成人一区二区三区片免费| 欧美日韩亚洲不卡| 亚洲二区在线观看| 久久爱另类一区二区小说| 性做久久久久久久免费看| 久久黄色小说| 麻豆成人在线播放| 亚洲国产一区视频| 日韩一级在线| 亚洲一区影院| 久久精品亚洲一区二区三区浴池| 欧美人成在线视频| 欧美三日本三级少妇三2023 | 欧美69wwwcom| 欧美h视频在线| 欧美精品v日韩精品v国产精品| 亚洲看片一区| 午夜精品99久久免费| 免费永久网站黄欧美| 欧美三区在线观看| 狠狠色综合色综合网络| 夜夜嗨av色一区二区不卡| 欧美一区二区三区四区在线| 免费观看一区| 一区二区三区高清| 麻豆九一精品爱看视频在线观看免费| 一区二区亚洲精品国产| 亚洲国产精品v| 亚洲欧美中文日韩在线| 国产精品毛片高清在线完整版| 亚洲男人的天堂在线aⅴ视频| 亚洲主播在线播放| 久久不见久久见免费视频1| 久久青青草原一区二区| 亚洲国产精品久久久久| 亚洲一区二区三区乱码aⅴ蜜桃女| 免费在线日韩av| 欧美成人按摩| 日韩视频精品在线| 久久99在线观看| 久久不射2019中文字幕| 最新国产精品拍自在线播放| 亚洲一区二区欧美日韩| 久久免费精品日本久久中文字幕| 亚洲国产成人久久| 久久高清国产| 亚洲三级免费电影| 久久久久久尹人网香蕉| 国产精品高潮呻吟视频| 99精品视频免费观看| 久久久久一区二区| 亚洲一区二区三区精品动漫| 欧美日本在线视频| 伊大人香蕉综合8在线视| 亚洲免费一级电影| 亚洲精品国产精品乱码不99 | 国产无遮挡一区二区三区毛片日本| 噜噜噜久久亚洲精品国产品小说| 亚洲免费影视第一页| 亚洲清纯自拍| 亚洲欧美国产日韩天堂区| 欧美+亚洲+精品+三区| 久久国产精品色婷婷| 国产精品嫩草99av在线| 亚洲三级视频在线观看| 久久天天躁狠狠躁夜夜爽蜜月| 欧美一级片久久久久久久| 国产精品v日韩精品| 亚洲愉拍自拍另类高清精品| 亚洲视频在线二区| 国产精品福利在线观看网址| 亚洲欧美一区二区三区久久| 亚洲永久字幕| 狠狠色狠狠色综合日日tαg| 免费日本视频一区| 欧美久久久久久蜜桃| 亚洲主播在线观看| 欧美一区二区视频在线观看2020| 在线成人性视频| 亚洲福利免费| 欧美午夜一区| 老司机午夜精品视频在线观看| 久久久www成人免费精品| 狠狠色2019综合网| 亚洲国产成人91精品| 欧美性一区二区| 欧美一区2区三区4区公司二百 | 午夜久久资源| 在线日韩视频| 亚洲免费播放| 国产一区二区三区观看| 亚洲电影天堂av| 国产精品成人免费| 日韩午夜精品| 国产亚洲一区精品| 麻豆精品视频在线观看| 欧美日韩精品一区二区三区| 性欧美大战久久久久久久久| 久久婷婷丁香| 亚洲欧美另类久久久精品2019| 亚洲欧美在线看| 洋洋av久久久久久久一区| 亚洲综合清纯丝袜自拍| 在线日韩欧美视频| 亚洲欧美自拍偷拍| 中文一区在线| 麻豆精品传媒视频| 欧美伊人久久| 欧美日韩免费在线视频| 裸体素人女欧美日韩| 国产精品永久在线| 在线午夜精品| 一区二区三区波多野结衣在线观看| 久久精品日韩欧美| 欧美一区在线直播| 国产精品黄色| 国色天香一区二区| 亚洲影视综合| 一区二区三区高清在线 | 欧美精品激情blacked18| 亚洲在线视频观看| 亚洲欧美日本国产有色| 一本色道久久精品| 久久蜜桃资源一区二区老牛| 亚洲愉拍自拍另类高清精品| 欧美成人r级一区二区三区| 亚洲免费av观看| 亚洲一区二区在线看| 99v久久综合狠狠综合久久| 久久影院亚洲| 欧美成人自拍| 激情文学综合丁香| 亚洲欧美春色| 在线性视频日韩欧美| 久久久久久自在自线| 午夜精品久久久久久久男人的天堂 | 亚洲精品欧美| 久久成人亚洲| 欧美伊人影院| 国产精品久久久久久久7电影| 麻豆精品视频在线| 狠狠久久亚洲欧美专区| 久久久.com| 久久免费精品视频| 国产一区欧美| 久久精品99久久香蕉国产色戒| 欧美亚洲一级片| 国产欧美一区二区精品秋霞影院| 欧美日韩亚洲另类| 亚洲欧美国产精品桃花| 欧美成人情趣视频| 亚洲日本电影| 欧美精品在线免费| 99这里只有久久精品视频| 亚洲自拍高清| 欧美好骚综合网| 亚洲一区二区三区午夜| 国产乱码精品一区二区三区忘忧草 | 国产一区二区日韩| 久久精品久久99精品久久| 久久先锋资源| 亚洲精品一区二区在线| 欧美激情视频一区二区三区在线播放 | 91久久精品久久国产性色也91| 日韩视频永久免费| 国产精品久久国产三级国电话系列 | 欧美在线一区二区三区| 美女主播一区| 亚洲在线一区| 亚洲精品一区在线| 国产日韩欧美制服另类| 欧美精品国产一区| 欧美一区二区三区免费视频| 亚洲人成在线播放| 欧美在线不卡| 一区二区精品| 亚洲福利视频一区| 欧美精品一区二| 欧美在线观看视频在线| 亚洲国内自拍| 欧美一区二区国产| 亚洲国产精品热久久| 久久综合一区二区| 麻豆精品在线观看| 亚洲精品一区二区在线观看| 亚洲三级免费电影| 久久精品二区| 一色屋精品视频免费看| 国产一区二区三区在线观看视频 | 欧美视频在线播放|