网络编程6: 如何将一个socket设置为非阻塞(windows和Linux)

如何将一个socket设置为非阻塞

一、函数标签

  • windows
#include<winsock2.h>
SOCKET WSAAPI socket( [in] int af, [in] int type, [in] int protocol);
// 参数
第一个参数:是协议族,常用的有 IF_INET,最常用的协议族,主要用于Internet进行通信,表示ipv4系列;IF_INET6-表示ipv6
第二个参数:socekt类型,常用的有SOCK_STREAM:创建的就是TCPsockt,SCOK_DGRAM:创建的就是UDPsocket
第三个参数:协议类型-使用的传输协议,常用的协议类型:IPPROTO_TCP:表示使用TCP协议进行通信,
		  IPPROTO_UDP:表示使用UDP协议进行通信
  • Linux
#inlcude<sys/types.h>
#include<sys/socket.h>
int socket(int domain,int type,int protocol);
//参数
第一个参数: 指定协议族,IF_INET:ipv4协议族,用于TCP/IP协议、AF_INET6:IPv6协议族,用于TCP/IP协议;AF_UNIX:本地通信协议族,
		  用于本地进程间通信(只在linux中);
第二个参数:指定socket类型,SOCK_STREAM:流式套接字,用于面向连接的数据传输,TCP协议;SOCK_DGRAM:数据报套接字,
		  用于无连接的数据传输,UDP协议;SOCK_RAW:原始套接字,用于底层数据通信;等等。相比Windows多个SOCK_NONBLOCK,
		  可以在创建的时候直接指定非阻塞模式
第三个参数:IPPROTO_TCP:TCP协议;IPPROTO_UDP:UDP协议;

二、window下

  1. 程序初始化的时候需要加载socket环境(dll)
#include<winsock2.h>
 	// 指定2.2版本,就是必须初始化2.2版本
	WORD wVersionRequested = MAKEWORD(2, 2);
	WSADATA wsaData;
	加载相关的dll,wsaData是输出参数
	int nErrorID = ::WSAStartup(wVersionRequested, &wsaData); 
	if(nErrorID != 0)
		//初始化失败
	//强制指定2.2,不是2.2就报错 
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
    	//不是指针版本
        ::WSACleanup();
    }
  1. 创建TCP socket
SOCKET socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socket_fd == INVALID_SOCKET) {
    // 创建socket失败
}
  1. 设置为非阻塞
unsigned long mode = 1;  // 阻塞模式设置为0就可以了
int result = ::ioctlsocket(socket_fd, FIONBIO, &mode);
// 入参FIONBIO基于变量mode来允许或禁止socekt的阻塞模式,
// mode=0就是阻塞模式,mode = 1就是非阻塞
if (result != 0) { // 
    // 设置非阻塞模式失败
}
  1. 关闭socket
closesocket(s);
  1. 进程退出时候需要卸载socket相关dll
::WSACleanup();
  1. TIP:
    WSAStartup() 和 WSACleanup() 是进程相关的,任何一个线程都可以调用,对于WSAStartup() 函数某个线程调用一次之后,其他线程就可以正常使用了;反过来,如果某个线程自己不再使用相关 socket 函数,如果其调用 WSACleanup()函数,会导致其他线程无法继续使用相关socket 函数。

三、Linux下

不需要加载socket环境,可以直接设置非阻塞模式

  1. 可以在创建socket的时候,直接指定为非阻塞
//可以在创建的TCP socket的时候来创建非阻塞模式,SOCK_NONBLOCK非阻塞标志
m_socket = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
// 关闭socket
close(s)
  1. 可以先创建默认阻塞的socket,通设置为非阻塞
#inlcude<sys/types.h>
#include<sys/socket.h>
// 创建socket
int socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socket_fd == -1) {
    // 创建socket失败
}
// 获取socket状态标志
int flags = fcntl(socket_fd, F_GETFL, 0); //F_GETFL:获取文件状态标志,
if (flags == -1) {
    // 获取socket状态失败
}
// 将状态标志添加socket的O_NONBLOCK
int result = fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK);
if (result == -1) {
    // 设置非阻塞模式失败
}
// 关闭socket
close(s)
  1. 关于fcntl函数(设置非阻塞)
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
fcntl用于控制文件描述符:进行文件描述符的复制,读写锁位置、非阻塞模式的这是等;
返回值为0表示成功,-1表示失败,可以用errno全局变量获取错误码;
参数说明,第一个参数:文件描述符;第二个参数:操作类型cmd;第三个参数,可选参数.用于传递具体的操作参数
cmd:
F_GETFD/F_SETFD:获取/设置 文件 描述符标志
F_GETFL/F_SETFL:获取/设置 文件 状态标志, arg(整数)表示要设置的文件状态标志:O_NONBLOCK等
*关于cmd还有其他的,可以自行查阅man手册!*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值