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

本文探讨了在游戏客户端测试过程中遇到的问题:使用非阻塞socket时connect调用返回-1的情况。文章解释了这一现象的原因,并提供了两种解决方案:通过select或poll模型判断socket是否可写来确认连接是否成功。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在开发游戏客户端测试程序时,由于出现很多客户端,经过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;
}


### lwIP 中 EINPROGRESS 错误码的含义 在 lwIP 网络协议栈中,`EINPROGRESS` 是一个标准的错误码,用于表示操作正在进行中,尚未完成。它通常出现在非阻塞模式下的套接字操作中[^1]。例如,当调用 `connect()` 函数连接到远程主机时,如果套接字处于非阻塞模式,则该函数可能不会立即完成连接过程,而是返回 `EINPROGRESS` 以通知调用者连接正在尝试建立,但尚未完成。 在 lwIP 的实现中,`EINPROGRESS` 的定义与 POSIX 标准兼容,其值通常为 `115`(具体值可能因平台而异)。这个错误码的意义在于告知应用程序开发者,当前的操作需要更多时间来完成,并且应该通过轮询或使用事件驱动的方式来检查操作的状态。 以下是一个简单的代码示例,展示如何处理非阻塞模式下返回 `EINPROGRESS` 的情况: ```c #include "lwip/sockets.h" #include "lwip/netdb.h" #include "lwip/err.h" int connect_with_einprogress(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { int err = connect(sockfd, addr, addrlen); if (err < 0) { int lwip_err = errno; if (lwip_err == EINPROGRESS) { // 连接正在尝试建立,需要等待 printf("Connection is in progress...\n"); return EINPROGRESS; } else { // 其他错误 printf("Connect error: %s\n", strerror(lwip_err)); return -1; } } // 连接成功 return 0; } ``` ### 注意事项 - 在非阻塞模式下,`EINPROGRESS` 是预期的行为,而不是真正的错误。 - 应用程序需要通过 `select()`、`poll()` 或其他机制来监控套接字的状态变化,以确定连接是否成功或失败[^1]。 - 如果套接字处于阻塞模式,则 `connect()` 函数会一直阻塞直到连接完成或超时,因此不会返回 `EINPROGRESS`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值