socket網路通訊
本文注意基於socket來分析tcp連線建立過程。
先回顧一下tcp連線建立過程:
主機a執行的是tcp客戶端程式,主機b執行的是tcp伺服器程式,最初兩端tcp程序處於closed態,a主動開啟連線,對應客戶端connect函式發起連線,b被動接受連線,對應於伺服器listen函式。
伺服器tcp程序先建立傳輸控制塊tcb,準備接受客戶程序的連線請求;
1 客戶端程序也首先建立tcb,然後通過connect函式向伺服器傳送連線請求,同步位syn=1(不攜帶資料),初始序列號seq=x,客戶端進入syn-sent態;
2 伺服器一直通過listen監控socket,接收到連線請求後,如同意連線,向客戶端發射確認,ack=1,syn=1,ack=x+1,seq=y;伺服器端進入syn-rcvd;
3 客戶端程序收到確認後,這時connect函式返回,對伺服器程序再確認,ack=1,seq=x+1,ack=y+1,客戶端進入連線態established 可讀寫;伺服器收到再次確認後也進入established 可讀寫。
對應socket可總結如下:
總結:客戶端的connect在三次握手的第二次返回,而伺服器端的accept在第三次握手的第三次返回。
tcp連線釋放過程:
tcp程序雙方都處於established態進行讀寫通訊,如果要釋放連線:
1 客戶端程序向伺服器發出釋放連線報文段,fin=1,seq=u,並停止傳送資料,此時客戶端進入fin-wait-1;
2 伺服器收到釋放報文請求後,發出確認ack=1,ack=u+1,seq=v,然後進入closed-wait態,客戶端收到確認訊息後進入fin-wait-2態,並等待伺服器發出連線釋放報文;
3 伺服器發出連線釋放請求,fin=1,ack=1,ack=u+1,seq=w,並進入last-ack;
4 客戶端收到伺服器釋放連線請求後,發出確認,ack=1,seq=u+1,ack=w+1,然後進入time-wait狀態,此時還需在等2msl(最長報文段壽命)後再進入closed。b收到確認訊息後立刻進入closed。
對應socket可總結如下:
某個應用程序首先呼叫close主動關閉連線,這時tcp傳送乙個fin m;
另一端接收到fin m之後,執行被動關閉,對這個fin進行確認。它的接收也作為檔案結束符傳遞給應用程序,因為fin的接收意味著應用程序在相應的連線上再也接收不到額外資料;一段時間之後,接收到檔案結束符的應用程序呼叫close關閉它的socket。這導致它的tcp也傳送乙個fin n;接收到這個fin的源傳送端tcp對它進行確認。這樣每個方向上都有乙個fin和ack。
最後,通過例程實踐,例程內容:
下面編寫乙個簡單的伺服器、客戶端(使用tcp)——伺服器端一直監聽本機的6666號埠,如果收到連線請求,將接收請求並接收客戶端發來的訊息;客戶端與伺服器端建立連線並傳送一條訊息
伺服器端**:
#include#include#include#include#include#include#include#define maxline 4096
int main(int argc, char** argv)
//呼叫socket函式
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = af_inet;
servaddr.sin_addr.s_addr = htonl(inaddr_any);//注意網路位元組序與本機位元組序
servaddr.sin_port = htons(6666);
if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1)//將socket繫結ip和埠
if( listen(listenfd, 10) == -1)//listen 該埠下的socket,輸入佇列額度10
printf("*****=waiting for client's request*****=\n");
while(1)//accept來自客戶端程序,注意此時產生乙個已建立socket描述符confd
n = recv(connfd, buff, maxline, 0);//讀入到buff
buff[n] = '\0';
printf("recv msg from client: %s\n", buff);
close(connfd);//結束
}close(listenfd);
}
客戶端**:
#include#include#include#include#include#include#include#define maxline 4096
int main(int argc, char** argv)
if( (sockfd = socket(af_inet, sock_stream, 0)) < 0)
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = af_inet;
servaddr.sin_port = htons(6666);
if( inet_pton(af_inet, argv[1], &servaddr.sin_addr) <= 0)
if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)//傳送請求
printf("send msg to server: \n");
fgets(sendline, 4096, stdin);
if( send(sockfd, sendline, strlen(sendline), 0) < 0)
//send函式,傳送sendline裡內容
close(sockfd);
exit(0);
}
這是乙個最基本socket通訊例程,上面的伺服器使用的是迭代模式的,即只有處理完乙個客戶端請求才會去處理下乙個客戶端的請求,這樣的伺服器處理能力是很弱的,現實中的伺服器都需要有併發處理。 Socket網路通訊
服務端的程式如下 1.建立乙個伺服器端socket,即serversocket,指定繫結的埠,並監聽此埠8888 serversocket serversocket new serversocket 8888 socket socket null 記錄客戶端的數量 int count 0 syste...
socket網路通訊
read write recv send readv writev recvmsg sendmsg recvfrom sendto include ssize t read int fd,void buf,size t count ssize t write int fd,const void bu...
網路通訊及Socket
1.物理層 提供資訊傳遞的媒介,如同軸電線 2.資料鏈路層 負責建立 維持和釋放資料連線,當接收點檢測到所傳資料中有錯,則會通知傳送失敗重發一遍 對資料的識別 3.網路層 當兩個計算機之間出現若高資料鏈的時候,網路層的任務就是在若干的資料鏈路中間選擇合適的鏈路確保資料的及時傳送 選擇合適的資料鏈路,...