socket傳送和接收資料

2021-09-07 22:36:39 字數 3307 閱讀 2702

1)sendbuf(),sendtext(),sendstream()

幾乎所有的通訊控制項都會提供上面的3個方法。首先看看sendbuf()。

function tcustomwinsocket.sendbuf(var buf; count: integer): integer;

varerrorcode: integer;

begin

lock;

tryresult := 0;

if not fconnected then exit;

result := send(fsocket, buf, count, 0);

if result = socket_error then

begin

errorcode := wsagetlasterror;

if (errorcode <> wsaewouldblock) then

begin

error(self, eesend, errorcode);

disconnect(fsocket);

if errorcode <> 0 then

raise esocketerror.createresfmt(@swindowssocketerror,

[syserrormessage(errorcode), errorcode, 'send']);

end;

end;

finally

unlock;

end;

end;

result := send(fsocket, buf, count, 0); // 傳送指定一塊指定大小的快取資料,指定多大就傳送多大,但一般不會超過32k的大小,至於太大的資料要如何處理,後面會作出講解。

接下來看下sendtext()。

function tcustomwinsocket.sendtext(const s: ansistring): integer;

begin

result := sendbuf(pointer(s)^, length(s) * sizeof(ansichar));

end;

原來是呼叫的sendbuf(),**就不作解釋。

最後看sendstream()。

function tcustomwinsocket.sendstream(astream: tstream): boolean;

begin

result := false;

if fsendstream = nil then

begin

fsendstream := astream;

result := sendstreampiece;

end;

end;

呼叫了sendstreampiece()。

function tcustomwinsocket.sendstreampiece: boolean;

varbuffer: array[0..4095] of byte;

startpos: integer;

amountinbuf: integer;

amountsent: integer;

errorcode: integer;

procedure dropstream;

begin

if fdropaftersend then disconnect(fsocket);

fdropaftersend := false;

fsendstream.free;

fsendstream := nil;

end;

begin

lock;

tryresult := false;

if fsendstream <> nil then

begin

if (fsocket = invalid_socket) or (not fconnected) then exit;

while true do

begin

startpos := fsendstream.position;

amountinbuf := fsendstream.read(buffer, sizeof(buffer));

if amountinbuf > 0 then

begin

amountsent := send(fsocket, buffer, amountinbuf, 0);

if amountsent = socket_error then

begin

errorcode := wsagetlasterror;

if errorcode <> wsaewouldblock then

begin

error(self, eesend, errorcode);

disconnect(fsocket);

dropstream;

if fasyncstyles <> then abort;

break;

end else

begin

fsendstream.position := startpos;

break;

end;

end else if amountinbuf > amountsent then

fsendstream.position := startpos + amountsent

else if fsendstream.position = fsendstream.size then

begin

dropstream;

break;

end;

end else

begin

dropstream;

break;

end;

end;

result := true;

end;

finally

unlock;

end;

end;

大的資料,一般超過32k,就用sendstream()傳送,先將資料一次性載入進流物件中,然後每次從流中讀取4k大小的資料進乙個記憶體塊中,然後通過socket傳送這個記憶體塊。

到這裡不免會產生幾個疑問。

大資料為什麼要分割成4k的小塊分作幾次傳送?

一是小塊傳輸增加了資料傳輸的可靠性,二是無形中增加了服務端的併發能力。

那麼服務端是怎麼接收和處理客戶端分割傳輸的資料?

這裡就涉及到"粘包「這個概念了,服務端先建立乙個流物件,將每次收到的小塊資料依次地寫進流物件中,在寫之前流的position+資料塊的長度,這樣通過流物件將這些小塊資料合併還原成乙個完整的資料。

socket資料的接收和傳送

linux 不區分套接字檔案和普通檔案,使用 write 可以向套接字中寫入資料,使用 read 可以從套接字中讀取資料。前面我們說過,兩台計算機之間的通訊相當於兩個套接字之間的通訊,在伺服器端用 write 向套接字寫入資料,客戶端就能收到,然後再使用 read 從套接字中讀取出來,就完成了一次通...

非同步 SOCKET 程式設計 傳送和接收資料

我本想把傳送和接收分開作為兩部分,但是最後我決定只略微解釋一下 fd read 留下更多的時間來說明更複雜的 fd write fd read 事件非常容易掌握.當有資料傳送過來時,winsock 會以 fd read 事件通知你,對於每乙個 fd read 事件,你需要像下面這樣呼叫 recv i...

非同步SOCKET程式設計 傳送和接收資料

基 本上就是這樣,別忘了修改上面的wparam.還有,不一定每一次呼叫recv 都會接收到乙個完整的資料報,因為資料可能不會一次性全部傳送過來.所 以在開始處理接收到的資料之前,最好對接收到的位元組數 即recv 的返回值 進行判斷,看看是否收到的是乙個完整的資料報.fd write相對來說就麻煩一...