socket api- c/s模式:服務讀寫,客戶寫讀. IO模式:阻塞

來源:互聯網
上載者:User

標籤:iostream   out   固定   logs   模式   style   字元   安全   clu   

 

服務端:socket->address->bind->listen->loop{accpet->read->write->close(auto socket)}->close(listen socket)
1)因為是阻塞模式,所以用戶端沒有關閉的時候,服務端會阻塞在read函數,
2)用戶端發送之後中斷連線。是一個有序的資料片。服務端由核心經過排序片。一定會接收到資料。
而不會因為close的資料先到就以為沒有資料。所以必須理解用戶端的行為。也就是write和close函數。
他們都是發送資料包。是有順序的,seq的。包括connect也是發送資料包。只不過工作由核心處理。
connect,write,close。如果按順序寫。發送的包的seq number是持續增加的。

 

用戶端:socket->connect->wirte->loop(read)->close(client socket)
1)因為是阻塞模式。服務端的read會阻塞。所以用戶端write之後再read。服務端是一定會接收到資料,再進行下一步發送資料的。
2)而用戶端也是阻塞模式。所以read是一定會等待服務端發來的資料。並等到服務端的close資訊。再完成接收資料步驟。


知識點:

char a[]=“” 會計算字元大小並加入結束符
read 函數,會讀入任何符號,包括結束符號。
snprintf(&buff,n,"",x),實際上的字元大小隻有n-1.會自動加入結束符號。

strlen 來計算實際的字元數量。不會包括結束符號。
1)所以write的時候用strlen確定實際字元大小。
2)read的時候。用一個n大小的char數組接收,並明確read的大小為n-1.方便放滿字元還可以自行加入結束符號。
3)每次讀之前,必須清空char數組,方便下次寫入。


未處理知識點:
1)因為是阻塞模式。服務端沒法確定用戶端不再發送資料。因為用戶端不可能關閉。它還要等待接收資料。
而用戶端不關閉。服務端,會一直阻塞在read函數。
所以本實驗是,客戶固定發送比較小的資料,服務端用較大的緩衝區一次接收完客戶資料。
而不考慮服務端一次接收不完的情況。
是否可以自己加入結束邊界標誌?對。書上好像提到過。應該是這樣處理。
2)如果服務端一次沒有讀完客戶資料。socket裡面還有資料。這個時候發送,是發送正常的?是因為socket有2個緩衝區還是,之前的緩衝區清空了?

 

 

 

server:

#include <iostream>#include <sys/socket.h>//{socket_type.h}:socket,AF_INET,SOCK_STREAM,PF_INET#include <netdb.h>//{<netinet/in.h>}:IPPROTO_TCP#include <sys/errno.h>#include <string.h>#include <stdio.h>//perror#include <fcntl.h>#include <unistd.h>//close.#include <time.h>#include <thread>#include <arpa/inet.h>//INET_PTONusing namespace std;typedef struct sockaddr_in SA;void Accpetthread(int serverFD);int main(){    //socket->addr->bind->listen->accept(read ,write)    int serverFD;    int intflag;    SA serverAddr;    bzero(&serverAddr,sizeof(serverAddr));    serverFD=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);    if(serverFD==-1)    {        perror("create()");        return -1;    }    //serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);    inet_pton(AF_INET,"127.0.0.1",&serverAddr.sin_addr);    serverAddr.sin_family=AF_INET;    serverAddr.sin_port=htons(3004);    //serverAddr.sin_zero??    intflag=bind(serverFD,(sockaddr*)&serverAddr,sizeof(sockaddr));    if(intflag==-1)    {        perror("bind()");        return -1;    }    listen(serverFD,10);//max queue?    thread a=thread(Accpetthread,serverFD);    a.detach();    int cmd;    cout<<"exist:input 88"<<endl;    for(;;)    {        cin>>cmd;        if(cmd==88)        {            break;        }    }    close(serverFD);//close 之後,地址不能使用.要等待2ml    return 0;}//void Accpetthread(int serverFD){    for(;;)    {        int serverTempFD=accept(serverFD,0,0);        //read        char readbuf[51];        int sizeread= read(serverTempFD,readbuf,50);        readbuf[sizeread]=‘\0‘;//以免溢出,插入結束符號.        char writebuff[100];        bzero(writebuff,100);//以免溢出,全部寫結束符號.        int tempsize= snprintf(writebuff,99,"%s:%d",readbuf,strlen(readbuf));        cout<<writebuff<<endl;        cout<<strlen(writebuff)<<endl;//為什麼size是100?不是根絕\0決定的嗎?        write(serverTempFD,writebuff,strlen(writebuff));        close(serverTempFD);    }}

 

client:

#include <iostream>#include <sys/socket.h>//{socket_type.h}:socket,AF_INET,SOCK_STREAM,PF_INET#include <netdb.h>//{<netinet/in.h>}:IPPROTO_TCP#include <sys/errno.h>#include <string.h>#include <stdio.h>//perror#include <fcntl.h>#include <unistd.h>//close.#include <time.h>#include <netinet/in.h>#include<arpa/inet.h>//INET_PTONusing namespace std;int main(){    //socket->connect->read.    int socketClientFD;    int statusFlag;    socketClientFD=socket(PF_INET,SOCK_STREAM,IPPROTO_IP);    if(socketClientFD==-1)    {        perror("socket()");        return -1;    }    struct sockaddr_in serverAddr;    bzero(&serverAddr,sizeof(serverAddr));    serverAddr.sin_family=AF_INET;    inet_pton(AF_INET,"127.0.0.1",&serverAddr.sin_addr);    //printf("%0x,%0x,%0x,%0x",((char*)&serverAddr.sin_addr)[0],((char*)&serverAddr.sin_addr)[1],((char*)&serverAddr.sin_addr)[2],((char*)&serverAddr.sin_addr)[3]);    serverAddr.sin_port=htons(3004);    statusFlag=connect(socketClientFD,(sockaddr*)&serverAddr,sizeof(serverAddr));    if(statusFlag==-1)    {        perror("connect()");        return -1;    }    char buff[11];    char writeChar[16]="hi,i am client.";//一定會加入結束符號.char 大小要比實際字元大1.    statusFlag= write(socketClientFD,writeChar,strlen(writeChar));//寫的時候只發送字元。不發送結束符。所以用strlen.    if(statusFlag==-1)    {        perror("write()");        return -1;    }    for(;;)    {        //bzero(buff,11);//每次要清空,更安全點。雖然後面已經buff[statusFlag]=‘\0‘;        statusFlag=read(socketClientFD,buff,10);//這裡會讀入任何符號。包括結束符號。所以要求寫的時候,不要發送結束符號。因此要求用strlen,確定實際字元。        if(statusFlag>0)        {            buff[statusFlag]=‘\0‘;            cout<<buff<<flush;        }        else if(statusFlag==0)        {            cout<<endl;            break;        }        else        {            perror("read()");            return -1;        }    }    cout<<"eixist:input 88."<<endl;    int cmd;    while(1)    {        cin>>cmd;        if(cmd==88)        {            close(socketClientFD);            break;        }    }    return 0;}

 

socket api- c/s模式:服務讀寫,客戶寫讀. IO模式:阻塞

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.