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相對來說就麻煩一...