首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

Linux 網絡編程:阻塞與非阻塞 Socket 的行為差異詳解

     編輯:C++ 入門

讀操作

阻塞 Socket

  • 接收緩衝區無數據 → read 一直阻塞,直到數據到達。
  • 緩衝區數據 < 期望讀取量 → 返回實際讀取字節數。
  • 緩衝區數據 ≥ 期望讀取量 → 讀取期望字節數並返回。

非阻塞 Socket

  • 無論緩衝區是否有數據,read 立即返回。
  • 有數據時行為同阻塞模式。
  • 無數據時返回 -1,errno = EWOULDBLOCK(操作本應阻塞但因非阻塞模式立即返回)。

典型讀取模式:

if ((nread = read(sock_fd, buffer, len)) < 0) {
    if (errno == EWOULDBLOCK) return 0; // 暫無數據
    else return -1; // 真正錯誤
}
return nread;

寫操作

阻塞 Socket

  • 發送緩衝區無空間/空間不足 → write 阻塞直到可寫。
  • 空間足夠 → 全部拷貝並返回字節數。

非阻塞 Socket

  • 發送緩衝區無空間 → 返回 -1,errno = EWOULDBLOCK。
  • 空間部分可用 → 拷貝盡可能多的數據,返回實際拷貝字節數。

典型寫入循環:

int write_pos = 0, nLeft = nLen;
while (nLeft > 0) {
    int nWrite = write(sock_fd, data + write_pos, nLeft);
    if (nWrite <= 0) {
        if (errno == EWOULDBLOCK) nWrite = 0;
        else return -1;
    }
    nLeft -= nWrite;
    write_pos += nWrite;
}
return nLen;

建立連接

  • 阻塞:connect 發送 SYN 並等待三次握手完成才返回。
  • 非阻塞:connect 發起握手後立即返回,errno = EINPROGRESS。後續需用 select/poll 監聽可寫事件判斷連接結果。

接收連接

  • 阻塞:accept 在連接隊列為空時阻塞。
  • 非阻塞:accept 立即返回,無連接時 errno = EWOULDBLOCK。

設置非阻塞模式

方法一:fcntl

int flag = fcntl(fd, F_GETFL, 0);
flag |= O_NONBLOCK;
fcntl(fd, F_SETFL, flag);

方法二:ioctl

int on = 1;
ioctl(fd, FIONBIO, &on);

總結

非阻塞 Socket 配合 I/O 多路復用(select/poll/epoll)是高併發服務器的基石,核心在於「不等待,輪詢就緒事件」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved