java socket 阻塞模式_(四) 如何將socket設置為非阻塞模式

1. windows平臺上無論利用socket()函數還是WSASocket()函數創建的socket都是阻塞模式的:

SOCKET WSAAPI socket( ? ?_In_ int af, ? ?_In_ int type, ? ?_In_ int protocol ? ); ? ? SOCKET WSASocket( ? ?_In_ int ? ? ? ? ? ? ? ?af, ? ?_In_ int ? ? ? ? ? ? ? ?type, ? ?_In_ int ? ? ? ? ? ? ? ?protocol, ? ?_In_ LPWSAPROTOCOL_INFO lpProtocolInfo, ? ?_In_ GROUP ? ? ? ? ?g, ? ?_In_ DWORD ? ? ? ? dwFlags ? );

linux平臺上可以在利用socket()函數創建socket時指定創建的socket是異步的:

int socket(int domain, int type, int protocol);

在type的參數中設置SOCK_NONBLOCK標志即可,例如:

int s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);

2. 另外,windows和linux平臺上accept()函數返回的socekt也是阻塞的,linux另外提供了一個accept4()函數,可以直接將返回的socket設置為非阻塞模式:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ? ? int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);

只要將accept4()最后一個參數flags設置成SOCK_NONBLOCK即可。

3. 除了創建socket時,將socket設置成非阻塞模式,還可以通過以下API函數來設置:

linux平臺上可以調用fcntl()或者ioctl()函數,實例如下:

fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK); ? ? ioctl(sockfd, FIONBIO, 1); ?//1:非阻塞 0:阻塞

參考:http://blog.sina.com.cn/s/blog_9373fc760101i72a.html

但是網上也有文章說(文章鏈接:http://blog.csdn.net/haoyu_linux/article/details/44306993),linux下如果調用fcntl()設置socket為非阻塞模式,不僅要設置O_NONBLOCK模式,還需要在接收和發送數據時,需要使用MSG_DONTWAIT標志,即在recv,recvfrom和send,sendto數據時,將flag設置為MSG_DONTWAIT。是否有要進行這種雙重設定的必要,筆者覺得沒有這個必要。因為linux man手冊上recv()函數的說明中關于MSG_DONTWAIT說明如下:

Enables nonblocking operation; if the operation would block, the call fails with the error EAGAIN or EWOULDBLOCK (this can also be enabled using the O_NONBLOCK flag with the F_SETFL fcntl(2)).

通過這段話我覺得要么通過設置recv()函數的flags標識位為MSG_DONTWAIT,要么通過fcntl()函數設置O_NONBLOCK標識,而不是要同時設定。

windows上可調用ioctlsocket函數:

int ioctlsocket( ? ?_In_ ? ?SOCKET s, ? ?_In_ ? ?long ? cmd, ? ?_Inout_ u_long *argp ? );

將cmd參數設置為FIONBIO,*argp=0即設置成阻塞模式,而*argp非0即可設置成非阻塞模式。但是windows平臺需要注意一個地方,如果你對一個socket調用了WSAAsyncSelect()或WSAEventSelect()函數后,你再調用ioctlsocket()函數將該socket設置為非阻塞模式,則會失敗,你必須先調用WSAAsyncSelect()通過設置lEvent參數為0或調用WSAEventSelect()通過設置lNetworkEvents參數為0來分別禁用WSAAsyncSelect()或WSAEventSelect()。再次調用ioctlsocket()將該socket設置成阻塞模式才會成功。因為調用WSAAsyncSelect()或WSAEventSelect()函數會自動將socket設置成非阻塞模式。msdn上的原話是:

The WSAAsyncSelect and WSAEventSelect functions automatically set a socket to nonblocking mode. If WSAAsyncSelect or WSAEventSelect has been issued on a socket, then any attempt to use ioctlsocket to set the socket back to blocking mode will fail with WSAEINVAL.

To set the socket back to blocking mode, an application must first disable WSAAsyncSelect by calling WSAAsyncSelect with the lEvent parameter equal to zero, or disable WSAEventSelect by calling WSAEventSelect with the lNetworkEvents parameter equal to zero.

網址:https://msdn.microsoft.com/en-us/library/windows/desktop/ms738573(v=vs.85).aspx

4. 在看實際項目中以前一些前輩留下來的代碼中,通過在一個循環里面調用fcntl()或者ioctlsocket()函數來socket的非阻塞模式的,代碼如下:

for (;;) ? { ? #ifdef UNIX ? ? ?on=1; ? ? ?if (ioctlsocket(id, FIONBIO, (char *)&on) < 0) ? #endif ? ? ? ? ? ? ? ? #ifdef WIN32 ? ? ?unsigned long on_windows=1; ? ? ?if (ioctlsocket(id, FIONBIO, &on_windows) < 0) ? #endif ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #ifdef VOS ? ? ?int off=0; ? ? ?if (ioctlsocket(id, FIONBIO, (char *)&off) <0) ? #endif ? ? ?{ ? ? ? ? ?if (GET_LAST_SOCK_ERROR() == EINTR) ? ? ? ? ? ? ?continue; ? ? ? ? ?RAISE_RUNTIME_ERROR("Can not set FIONBIO for socket"); ? ? ? ? ?closesocket(id); ? ? ? ? ?return NULL; ? ? ?} ? ? ?break; ? }

是否有必要這樣做,有待考證。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/533624.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533624.shtml
英文地址,請注明出處:http://en.pswp.cn/news/533624.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python中的pygame模塊使用方法_Pygame的基本使用

Pygame有很多模塊&#xff0c;每個模塊又有很多方法&#xff0c;在此不能夠逐一講解&#xff0c;所以&#xff0c;我們通過一個實例來學習Pygame&#xff0c;然后再分解代碼&#xff0c;講解代碼中的模塊。例&#xff1a;制作一個跳躍的小球游戲。創建一個游戲窗口&#xff0c;…

java mongodb 插入數據_mongoDB 插入數據 用java實現

import java.net.UnknownHostException;import com.mongodb.BasicDBObject;import com.mongodb.DB;import com.mongodb.DBCollection;import com.mongodb.DBObject;import com.mongodb.Mongo;/** *用java 往mongoDB插入數據 * author wwd* */public class InsertData {publi…

python的特征提取實驗一_Spark 2.1.0 入門:特征抽取 — TF-IDF(Python版)

這一部分我們主要介紹和特征處理相關的算法&#xff0c;大體分為以下三類&#xff1a;特征抽取&#xff1a;從原始數據中抽取特征特征轉換&#xff1a;特征的維度、特征的轉化、特征的修改特征選取&#xff1a;從大規模特征集中選取一個子集特征提取TF-IDF (HashingTF and IDF)…

java addlast_Java中的LinkedList addLast()方法: java.util.LinkedList.addLast() - Break易站

Java中的java.util.LinkedList.addLast()方法用于在LinkedList的末尾插入特定元素。句法&#xff1a;void addLast(Object element)參數&#xff1a;此函數接受單個參數元素&#xff0c;如上面的語法所示。此參數指定的元素將附加在列表的末尾。返回值&#xff1a;此方法不返回…

macos降級_iOS12.3 beta2更新了什么 iOS12.3測試版2新特性與升降級方法

4月0日凌晨&#xff0c;蘋果發布了iOS12.3 beta2&#xff0c;作為iOS12.3第二個測試版&#xff0c;相比前一個版本&#xff0c;發布時間間隔近2周&#xff0c;這次依然是小版本更新&#xff0c;不過相對良心一些&#xff0c;主要是多了一些與國內用戶相關的東西。iOS12.3 beta …

java技術教程視頻_Spring開發視頻教程高級篇+源碼(400M)33講

Spring開發視頻教程高級篇源碼(400M)33講01_全面闡釋Spring及其各項功能.rar 02_搭建與測試Spring的開發環境.rar 03_編碼剖析Spring管理Bean的原理.rar 04_Spring的三種實例化Bean的方式.rar 05_配置Spring管理的bean的作用域.rar 06_Spring管理的Bean的生命周期.rar 07_編碼剖…

python的常見矩陣除法_Numpy矩陣除法返回所有零

我對下面的矩陣有個除法錯誤。我想用行和的101向量除以1010matrix。在[[5731, 3, 20, 8, 12, 54, 46, 8, 39, 2],[ 2, 6472, 47, 24, 7, 44, 7, 11, 116, 12],[ 55, 36, 5296, 104, 84, 27, 106, 53, 183, 14],[ 50, 49, 132, 5312, 2, 253, 36, 58, 142, 97],[ 16, 28, 36, 9,…

java rc2加密_急求java RC2加密算法

下面是一段C RC2加密 要求要用java 重寫 能互相加密解密QSBEncryptRc2::QSBEncryptRc2(){EncryKey "DingXin Communication Key 20080613";}//解密失敗時返回失敗描述AnsiString QSBEncryptRc2::GetDecryptErrMsg(){int ErrorCode;AnsiString ErrMsg;ErrorCode …

linux配置usb主從_雜集:淺談關于Mongodb數據庫主從復制

Linux下Mongodb數據庫主從復制配置Mongodb的三種集群搭建的方式&#xff1a;Master-Slaver&#xff1a;主從[目前被副本集取代]。Replica Set&#xff1a;副本集。Sharding&#xff1a;切片。Mongodb單實例缺點&#xff1a;適合簡易開發時使用&#xff0c;生產使用不行&#xf…

java讀取郵箱附件_使用javamail獲取附件內容

我正在使用javamail來自動化一些電子郵件處理。使用javamail獲取附件內容我設法連接到pop3服務器并獲取消息。其中一些包含附件。根據郵件標題&#xff0c;我可以“預測”我需要獲取的附件的文件名。但我無法得到它的內容:(我有一個函數public byte[] searchForContent(Part pa…

高斯擬合 vc++代碼_NMA2020W1 極大似然法模型擬合與bootstrap

常見的線性模型&#xff1a; 求解方式有兩種&#xff0c;一種是計算均方誤差&#xff08;MSE&#xff09;&#xff0c;使得均方誤差最小。圖1找到梯度為零的點即可。而之前一直比較模糊的最大似然法也比較清楚了。一般線性模型&#xff0c;我們假定誤差項是符合高斯分布的&…

java文件快速掃描儀_Java掃描儀具有示例的NextNextShort()方法

掃描儀類hasNextShort()方法語法&#xff1a;public boolean hasNextShort();public boolean hasNextShort(int rad);hasNextShort()方法在java.util包中可用。hasNextShort()方法用于檢查此掃描程序在其輸入中是否具有下一個標記&#xff0c;是否可以將其作為隱式基數中的shor…

python sqlite并發處理_python sqlite大數據 處理

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里技術人對外發布原創技術內容的最大平臺&…

java sax xml文件解析_java解析xml文件-DOM/SAX

java解析xml文件的兩種方式1&#xff1a;DOM原理&#xff1a;把整個文檔加載到內存&#xff0c;轉化成dom樹&#xff0c;之后應用程序可以隨機的訪問dom樹的任何數據&#xff0c;靈活 快&#xff0c;但消耗內存一個簡單的xml使用java解析//builder工廠DocumentBuilderFactory f…

python現有兩個磁盤文件a和b_有兩個磁盤文件A和B,各存放一行字母,今要求把這兩個文件中的信息合并,輸出到一個新文件C中。...

首先&#xff0c;在.cpp所在的文件夾下建立A.txt與B.txt。向其中輸入字母。#include#include#includeint main(){FILE *a,*b,*c;char ch[100],outfile[10];int i0,n;void paixu(char a[100],int n);if((afopen("A.txt","r"))NULL){printf("Cant open …

python 遠程控制_用 Python 遠程控制你的電腦

用 Python 遠程控制你的電腦一、前言很多時候我們有這種需求&#xff0c;因為程序運行比較耗時&#xff0c;但是我們沒有足夠的時間等待。這個時候我們就可以用 Python 做一個遠程控制電腦的小工具&#xff0c;實現遠程控制電腦。當然&#xff0c;我們能做的操作十分有限&#…

攝像頭圖像分析目標物體大小位置_一文讀懂圖像定位及跟蹤技術

文 | 傳感器技術在科學技術日新月異的今天&#xff0c;人們對機器設備的智能性、自主性要求也越來越高&#xff0c;希望其完全替代人的角色&#xff0c;把人們從繁重、危險的工作任務中解脫出來&#xff0c;而能否像人一樣具有感知周圍環境的能力已成為設備實現智能化自主化的關…

java 相對路徑獲取_在java項目中通過相對路徑獲取資源的方式

1.可以通過 類名.class.getResource方法獲取或者getSystemResource2.可以通過當前線程 Thread.currentThread().getContextClassLoader().getResource獲取public class TestDemo {public static void main(String[] args) throws FileNotFoundException, IOException {Properti…

python循環嵌套的外循環必須完全包含內循環_Python:循環與嵌套循環實現規律數列...

很多人覺得編程很難&#xff0c;其實換個想法&#xff0c;這就是個用來解決問題的工具&#xff0c;我們為了解決實際問題而來學習和使用編程&#xff0c;這樣編程學習有了目的性&#xff0c;動力會更強。就像現在十分熱門的Python技術&#xff0c;就是人工智能領域所需求的&…

python爬取正確但不出文件_使用BeautifulSoup進行Python抓取時不顯示所有行

我是美容小組的新手。我試圖從ESPN Fantasy Basketball Standings中獲取“Season Stats”表&#xff0c;但并不是返回所有行。經過一番研究&#xff0c;我認為這可能是一個問題html.parser&#xff0c;所以我用了lxml。我得到了同樣的結果。如果有人能告訴我如何得到所有球隊的…