Linux下TCP迴圈接收資料的方式
阿新 • • 發佈:2019-01-13
簡介
伺服器呼叫accept
與客戶端建立連線,連線建立成功後,會返回一個fd,表示這條了連線的檔案描述符。之後呼叫recv
函式接受連線的資訊。根據recv函式的原型,需要伺服器程式有一個接收緩衝區,實際情況可能緩衝區長度不夠,需要多次接收。這時候需要呼叫while迴圈接收。
如果連線建立成功,而且有資料發過來,但是此時的伺服器沒有及時處理,那麼訊息會放到緩衝區中,直到使用recv函式接收。也就是說,接收資料由核心完成並放到有關的緩衝區當中,recv的接收實際上是從核心中進行讀取。下面的20秒就是模擬這個過程。
程式碼例項
非阻塞方式,一次性接受完成後就退出
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <thread>
#include <chrono>
#include <netinet/ip.h>
#include <iostream>
int main() {
int ret, listenfd;
struct sockaddr_in serv_addr;
bzero (&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8001);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd < 0) {
perror("socket() error\n");
return 0;
}
ret = bind(listenfd, ( struct sockaddr*)&serv_addr, sizeof(serv_addr));
if (ret < 0) {
perror("bind() error\n");
return 0;
}
ret = listen(listenfd, 1000);
if (ret < 0) {
perror("listen() error\n");
return 0;
}
int connfd = accept(listenfd, NULL, NULL);
if (connfd < 0) {
perror("accept() error\n");
return 0;
}
std::cout << "sleep for 20 seconds...\n";
std::this_thread::sleep_for(std::chrono::seconds(20));
std::cout << "weak up\n";
char buf[100];
memset(buf, 0, 100);
// 這裡是非阻塞,如果是阻塞方式,把MAG_DONTWAIT改成0即可
while (recv(connfd, buf, sizeof(buf), MSG_DONTWAIT) > 0) {
std::cout << "\nreceive message: " << buf;
memset(buf, 0, sizeof(buf));
}
return 0;
}