從寫乙個tcp套接字的write呼叫成功返回僅僅表示我們可以重新使用原來的應用程序緩衝區,並不代表對端tcp或應用程序已接收到資料。
對端tcp必須確認收到的資料,伴隨來自對端的ack的不斷到達,本端tcp至此才能從套接字傳送緩衝區中丟棄已確認的資料,tcp必須為已傳送的資料保留乙個副本,直到它被對端確認為止。
udp不儲存應用程序資料的副本因此無需乙個真正的傳送緩衝區,write呼叫成功返回表示所寫的資料報或其所有分片已被加入資料鏈路層的輸出佇列。
對於read呼叫(套接字標誌為阻塞),如果接收緩衝區中有20位元組,請求讀100個位元組,就會返回20。對於write呼叫(套接字標誌為阻塞),如果請求寫100個位元組,而傳送緩衝區中只有20個位元組的空閒位置,那麼write會阻塞,直到把100個位元組全部交給傳送緩衝區才返回,如果write中得套接字標誌為非阻塞,則直接返回20,因此我們可以實現自己的readn和writen函式。
每個tcp套接字都有乙個傳送緩衝區和乙個接收緩衝區,每個udp套接字都有乙個接收緩衝區;
先模擬服務端阻塞:
client:
[cpp]view plain
copy
struct
sockaddr_in serveradd;
bzero(&serveradd, sizeof
(serveradd));
serveradd.sin_family = af_inet;
serveradd.sin_addr.s_addr = inet_addr(serv_addr);
serveradd.sin_port = htons(serv_port);
connfd = socket(af_inet, sock_stream, 0);
intconnresult = connect(connfd, (
struct
sockaddr *)&serveradd,
sizeof
(serveradd));
if(connresult
else
ssize_t writelen;
char
sendmsg[246988] = ;
intcount = 0;
while
(1)
writelen = write(connfd, sendmsg, sizeof
(sendmsg));
if(writelen
else
}
server:
[cpp]view plain
copy
intmain(
intargc,
const
char
* argv)
intbindresult = bind(listenfd, (
struct
sockaddr *)&serveradd,
sizeof
(serveradd));
if(bindresult
else
listen(listenfd, 20);
intconnfd;
unsigned char
recvmsg[246988];
clientaddrlen = sizeof
(clientadd);
connfd = accept(listenfd,(struct
sockaddr *)&clientadd,&clientaddrlen);
if(connfd
else
printf("the recv buf len: %d\n"
, rcvbuf_len );
} ssize_t totallen = 0;
while
(1)
else
if(readlen == 0)
else
} close(connfd);
return
0;
}
TCP之Socket的程式設計
socket是網路程式設計的乙個抽象的概念,通常我們用socket來表示伺服器與客戶端間的網路連線,即用socket表示 開啟了乙個網路連線 而開啟乙個網路連線需要知道目標電腦的ip位址以及埠號,然後指定協議的型別即可。大多數的連線都是可靠的tcp連線,在建立tcp時,主動發起請求的就是客戶端,被動...
socket網路程式設計學習之tcp與udp
不管你採用的是哪種位址家族,都有兩種不同風格的套接字連線。第一種是面向連線的 這意味著在進行通訊之前必須先建立乙個連線,例如,使用 系統給乙個朋友打 這 種型別的通訊也稱為虛擬電路或流套接字。48 第 1 部分 通用應用主題 面向連線的通訊提供序列化的 可靠的和不重複的資料交付,而沒有記錄邊界。這基...
socket網路程式設計tcp
usr bin env python coding utf 8 tcp 客戶端 import socket host 127.0.0.1 post 3214 s socket.socket try s.connect host,post data 你好!while data s.sendall da...