socket網路程式設計之TCP Client

2021-06-27 07:32:05 字數 3032 閱讀 3989

#include #include #include #include dword winapi recvproc(

lpvoid lpparameter // thread data

);bool g_brun;

void main()

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

socket socketclt = socket(af_inet, sock_stream, 0);

sockaddr_in addrclt;

addrclt.sin_addr.s_un.s_addr = inet_addr("172.20.33.82");

addrclt.sin_family = af_inet;

addrclt.sin_port = htons(5000);

int i= connect(socketclt, (sockaddr *)&addrclt, sizeof(sockaddr));

if(i==0)

else

handle hrecvthread;

hrecvthread=createthread(null,0,recvproc,(lpvoid)socketclt,0,null);

char ch;

while(1) }

}dword winapi recvproc(

lpvoid lpparameter // thread data

)else if(len==0)

for(int i=0;i    在資料接收執行緒中,recv函式阻塞當前執行緒等待資料到來,返回實際copy的位元組數(copy表示tcp/ip協議將資料拷貝到socketclient指定的緩衝區中),如果在copy的時候出現網路錯誤(比如被其它應用程式中斷),那麼它將返回socket_error(-1),這時可呼叫getlasterror()查詢錯誤原因,如果伺服器「優雅」的中斷了鏈結,那麼它將返回0。

如果socketclient接收緩衝區中沒有資料或者協議正在接收資料,那麼recv就一直等待(阻塞),直到協議把資料接收完畢,當資料接收完畢,recv就把socketclient接收快取區的資料copy到recvbuf中。

注意:

1. 協議接收到的資料可能大於recvbuf的長度,所以在這種情況下要呼叫幾次recv函式才能把s的接收緩衝中的資料copy完。recv函式僅僅是copy資料,真正的接收資料是協議來完成的。

(對於winsock, afd.sys驅動負責緩衝區的管理,也就是說,當乙個程式呼叫send或wsasend函式傳送資料的時候,資料被複製到afd.sys的內部緩衝裡(大小根據so_sndbuf設定),然後send和wsasend立刻返回。之後資料由afd.sys負責傳送到網路上,與應用程式無關。當然,如果應用程式希望傳送比so_sndbuf設定的緩衝區還大的資料,wsasend函式將會被堵塞,直到所有資料均被傳送完畢為止。同樣,當從遠地客戶端接受資料的時候,如果應用程式沒有提交receive請求,而且線上資料沒有超出so_rcvbuf設定的緩衝大小,那麼afd.sys就把網路上的資料複製到自己的內部緩衝儲存。當應用程式呼叫recv或wsarecv函式的時候,資料即從afd.sys的緩衝複製到應用程式提供的緩衝區裡。)

2. tcp是一種流式的協議,傳送方在傳送乙個固定長度資料時,可能被拆成多個包傳送,因此接收方就需要進行多次接收,直到接收完整。比如傳送500位元組資料,可能傳送的時候就被拆成100,200,200傳送,接收的時候就要讀取3次。

3. windows預設的socket快取區大小為8k,如果要重新設定緩衝區大小可呼叫以下函式,但不建議修改:

int setsockopt( socket s,

int level, // sol_socket

int optname, // so_rcvbuf or so_sndbuf

const char* optval,

int optlen

);

示例**如下所示(注意須在connect函式之前設定):

int optval = 1024*20; // 20k

int optlen = sizeof(int);

setsockopt(socksrv, sol_socket, so_rcvbuf, (char *)&optval, optlen);

char *buf;

#define buf_len 10*1024*1024//10mb

buf = new char[buf_len];//此時buf當中都是隨機資料,實際需要的話,自己填充

int ineedsend = buf_len;

char *p = buf;

while(ineedsend)

delete buf;

ps:在實際應用中,伺服器端以固定的速率(大概200kb/s)傳送128位元組資料,接收的時候發現被拆包,大部分時候是以112和16接收。最終資料儲存完整,沒有出現丟包現象。

作為乙個套接字,它擁有兩個緩衝,接收資料緩衝和傳送資料緩衝(此緩衝不同與你自己定義的緩衝),當有資料到達時,首先進入的就是接收資料緩衝,然後使用者從這個緩衝中將資料讀出來,這就是套接字接受的過程,這個緩衝的大小可以自己用setsocketopt()設定,同時作業系統對它有乙個預設大小,如果對方在很短時間內傳送大量資料到達這個套接子時,可能它沒來得及接收完,因此接收緩衝處於滿的狀態,再有資料來的時候就進不去了,因此對方的 send可能就返回錯誤,在對方傳送的資料量很小時不會出現這種情況,當資料量很大時,情況就很明顯了,很容易造成收不到的情況。同樣,傳送方的傳送緩衝也有相對應的問題。解決這個問題的辦法有幾種:  

1. 利用setsocketopt()函式將接收方套接子接收緩衝設為足夠大小;  

2. 傳送方進行資料傳送時判斷傳送是否成功,如果不成功重發;  

3. 要求接收方收到資料後給傳送方回應,傳送方只在收到回應後才傳送下一條資料。

網路程式設計之socket

套接字 socket 是乙個抽象層,應用程式可以通過它傳送或接收資料,可對其進行像對檔案一樣的開啟 讀寫和關閉等操作。套接字允許應用程式將i o插入到網路中,並與網路中的其他應用程式進行通訊。網路套接字是ip位址與埠的組合。套接字起源於 20 世紀 70 年代加利福尼亞大學伯克利分校版本的 unix...

網路程式設計之socket

1,socket 通訊 服務端 import socket server socket.socket server.bind 127.0.0.1,8080 server.listen 5 conn,addr server.accept data conn.recv 1024 print data c...

網路程式設計之socket

1 是什麼?socket又稱套接字,是能夠實現程序間通訊的乙個 東西 2 為什麼?socket是對tcp ip協議的乙個封裝,相當於軟體設計模式中的外觀者模式 socket作為按鈕,按鈕內部連線著tcp ip的若干個對應的協議,也其實可以簡單理解為socket內部封裝著與tcp ip參考模型中各層進...