基於TCP和UDP的socket通訊(C 實現)

2021-09-30 14:42:03 字數 3764 閱讀 8125

**:

首先談談tcp socket

tcp簡單的三次握手過程如圖,

syn(synchronize sequence numbers):同步標誌  

ack(acknowledgement number)        :確認標誌

圖中可以看出,三次握手的過程是在c的connect()和s的bind()、listen()、accept()函式中完成的,這樣開闢了相對可靠的連線通道,來傳輸資料。

udp的socket程式設計過程如下圖所示:

下面上**

服務端:

[cpp]view plain

copy

#include 

#include //windows socket的標頭檔案

#pragma comment( lib, "ws2_32.lib" )// 鏈結winsock2.h的靜態庫檔案

void

main()  

if( lobyte( wsadata.wversion ) != 1 ||hibyte( wsadata.wversion ) != 1 )

//lobyte()取得16進製制數最低位;hibyte()取得16進製制數最高(最左邊)那個位元組的內容      

socket socksrv=socket(af_inet,sock_stream,0);//建立socket。af_inet表示在internet中通訊;sock_stream表示socket是流套接字,對應tcp;0指定網路協議為tcp/ip

sockaddr_in addrsrv;   

addrsrv.sin_addr.s_un.s_addr=htonl(inaddr_any); //htonl用來將主機位元組順序轉換為網路位元組順序(to network long)

//inaddr_any就是指定位址為0.0.0.0的位址,

//表示不確定位址,或「任意位址」。」

addrsrv.sin_family=af_inet;   

addrsrv.sin_port=htons(4000);//htons用來將主機位元組順序轉換為網路位元組順序(to network short)

bind(socksrv,(sockaddr*)&addrsrv,sizeof

(sockaddr));

//將本地位址繫結到所建立的socket上,以使在網路上標識該socket

listen(socksrv,5);//socket監聽,準備接受連線請求。

sockaddr_in addrclient;  

intlen=

sizeof

(sockaddr);  

while

(1)  

wsacleanup();  

}  

客戶端:

[cpp]view plain

copy

#include 

#include 

#pragma comment( lib, "ws2_32.lib" ) 

void

main()  

if( lobyte( wsadata.wversion ) != 1 ||hibyte( wsadata.wversion ) != 1 )

//lobyte()取得16進製制數最低位;hibyte()取得16進製制數最高(最左邊)那個位元組的內容      

for(int

index=0;;index++)  

wsacleanup();  

}  

對於tcp socket,有幾點需要注意:

一、tcp的time_wait狀態(等待客戶端的相應)    

注*time_wait 狀態最大保持時間是2 * msl,也就是1-4分鐘(msl是最大分段生存期,指明tcp報文在internet上最長生存時間)

當伺服器端socket繫結本地位址並占用了埠,此時如果匆忙結束;或者連線的伺服器異常退出,這個時候被占用的埠不能馬上釋放,需要time_wait。即便呼叫closesocket()一般也不會立即關閉socket,仍可繼續重用該socket。所以重新啟動伺服器時可能會出現問題。例如mfc中在子視窗中實現socket通訊,那麼關閉子視窗再開啟就會出問題了。

解決方法是在bind()之前新增setsockopt()函式,解除埠繫結。

介紹setsockopt()之前我們再來回顧一下三次握手協議的具體流程:

第一次握手:建立連線時,客戶端傳送syn包(syn=j)到伺服器,並進入syn_send狀態,等待伺服器確認; 

第二次握手:伺服器收到syn包,必須確認客戶的syn(ack=j+1),同時自己也傳送乙個syn包(syn=k),即syn+ack包,此時伺服器進入syn_recv狀態; 

第三次握手:客戶端收到伺服器的syn+ack包,向伺服器傳送確認包ack(ack=k+1),此包傳送完畢,客戶端和伺服器進入established狀態,完成三次握手。 

完成三次握手,客戶端與伺服器開始傳送資料。

setsockopt()使用方法如下:

二、對於大型檔案,一般需要將其剁碎了一部分一部分的傳。tcp不能保證接收方順序的收到包,對於需要實時顯示的檔案可以在傳送方發出包後設定來自接收方的響應,即對方收到前乙個包後再傳送下乙個包。

下面簡單說下udp socket

udp不能保證雙方的可靠連線,容易出現丟包現象。

udp的socket程式設計過程如下圖所示:

上**了。

服務端:

[cpp]view plain

copy

#include 

#include 

#pragma comment( lib, "ws2_32.lib" ) 

void

main()  

if( lobyte( wsadata.wversion ) != 1 ||  

hibyte( wsadata.wversion ) != 1 )   

socket socksrv=socket(af_inet,sock_dgram,0);  

intlen=

sizeof

(sockaddr);  

sockaddr_in from;     

sockaddr_in local;   

local.sin_addr.s_un.s_addr=htonl(inaddr_any);   

local.sin_family=af_inet;   

local.sin_port=htons(27015);   

inta = bind(socksrv,(sockaddr*)&local,len);  

while

(1)  

closesocket(socksrv);  

wsacleanup();  

}  

客戶端:

[cpp]view plain

copy

#include 

#include 

#pragma comment( lib, "ws2_32.lib" ) 

void

main()  

if( lobyte( wsadata.wversion ) != 1 ||  

hibyte( wsadata.wversion ) != 1 )   

for(

intindex=0;;index++)  

}  

基於UDP和TCP實現CS

1.我們應該先了解udp和tcp協議 首先udp和tcp是基於傳輸層的協議 我們需要了解udp和tcp的特性 tcp協議的特性 1 面向連線的服務 2 可靠的資料傳輸服務 3 面向位元組流。udp協議的特性 1 無連線服務 2 不可靠的資料傳輸 3 面向資料報 以下是流行網際網路應用層及其應用層協議...

基於tcp和udp的socket通訊

做個小遊戲的project用到了socket程式設計,於是,就在網上查閱了一下資料,下面簡單總結一下。1.什麼是socket socket是在應用層與傳輸層之間的乙個抽象層,它把tcp ip層複雜的操作抽象為幾個介面 用層的程序實現網路通訊,使得不同主機的相關程序之間交換資料。2.什麼是tcp和ud...

基於Socket的UDP和TCP協議

一 概述 tcp 傳輸控制協議 和udp 使用者資料報協議 是網路體系結構tcp ip模型中傳輸層一層中的兩個不同的通訊協議。tcp 傳輸控制協議,一種面向連線的協議,給使用者程序提供可靠的全雙工的位元組流,tcp套介面是位元組流套介面 stream socket 的一種。udp 使用者資料報協議。...