非阻塞情况下connect产生EINPROGRESS错误

今天在开发游戏客户端测试程序时,由于出现很多客户端,经过connect成功后,代码卡在recv系统调用中,后来发现可能是由于socket默认是阻塞模式,所以会令很多客户端

链接处于链接却不能传输数据状态。


后来修改socket为非阻塞模式,但在connect的时候,发现返回值为-1,刚开始以为是connect出现错误,但在服务器上看到了链接是ESTABLISED状态。证明链接是成功的

但为什么会出现返回值是-1呢? 经过查询资料,以及看stevens的APUE,也发现有这么一说。


当connect在非阻塞模式下,会出现返回-1值,错误码是EINPROGRESS,但如何判断connect是联通的呢?stevens书中说明要在connect后,继续判断该socket是否可写?


若可写,则证明链接成功。如何判断可写,有2种方案,一种是select判断是否可写,二用poll模型。


select:

int CheckConnect(int iSocket)
{
	fd_set rset;

	FD_ZERO(&rset);
	FD_SET(iSocket, &rset);

	timeval tm;
	tm. tv_sec = 0;
	tm.tv_usec = 0;

	if ( select(iSocket + 1, NULL, &rset, NULL, &tval) <= 0)
	{
    		close(iSocket);
    		return -1;
	}

	if (FD_ISSET(iSocket, &rset))
	{
    		int err = -1;
    		socklen_t len = sizeof(int);
	if ( getsockopt(iSocket,  SOL_SOCKET, SO_ERROR ,&err, &len) < 0 )
	{
    		close(iSocket);
    		printf("errno:%d %s\n", errno, strerror(errno));
   		return -2;
	}

	if (err)
	{
  	 	errno = err;
    		close(iSocket);
   
  		return -3;
	}
	return 0;
}

poll:

int CheckConnect(int iSocket) {
	struct pollfd fd;
	int ret = 0;
	socklen_t len = 0;

	fd.fd = iSocket;
	fd.events = POLLOUT;

	while ( poll (&fd, 1, -1) == -1 ) {
		if( errno != EINTR ){
			perror("poll");
			return -1;
		}
	}

	len = sizeof(ret);
	if ( getsockopt (iSocket, SOL_SOCKET, SO_ERROR, &ret, &len) == -1 ) {
    	        perror("getsockopt");
		return -1;
	}

	if(ret != 0) {
		fprintf (stderr, "socket %d connect failed: %s\n",
                 iSocket, strerror (ret));
		return -1;
	}

	return 0;
}


`kernel_connect()`函数通常是在Linux系统编程中使用的,它用于创建一个套接字并连接到指定的服务器地址。这个函数本身并不支持直接设置为阻塞模式;它是用于初始化连接操作,而不是控制连接是否阻塞。 如果你想要让连接过程变为阻塞的,你应该在调用`connect()`函数时设置对应的标志,特别是在使用`socket()`函数创建套接字时。对于大多数编程语言如C/C++,你可以这样做: ```c int socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 0) { // 错误处理 } struct sockaddr_in server_address; // 初始化server_address int flags = fcntl(socket_fd, F_GETFL, 0); // 获取现有标志 fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK); // 设置为非阻塞模式 if (connect(socket_fd, (struct sockaddr *)&server_address, sizeof(server_address)) == -1 && errno != EINPROGRESS) { // 非阻塞连接失败,检查错误 } else { // 如果errno是EINPROGRESS,则说明连接请求已经发送,并进入非阻塞状态,需要通过epoll、select等机制来监听连接结果 } // 后续可以使用epoll或select来检查连接完成,或者再次设置为阻塞模式 fcntl(socket_fd, F_SETFL, flags & ~O_NONBLOCK); // 如果需要等待连接完成 ``` 这里的关键在于`fcntl()`函数,你可以通过修改它的第三个参数来改变套接字的行为。但是请注意,频繁地在阻塞和非阻塞之间切换可能会导致性能问题,因此应谨慎使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值