TCP/IP协议: connect的系统超时控制

 在使用TCP的connect连接服务器时,在默认情况下系统使用的是阻塞式socket,如果服务器当前不可用,则connect会等待直到超时时间到达(大多数伯克利系统将建立一个新连接的最长时间限制为75秒),而这个超时时间是系统内核规定的,并不能使用setSocketOpt来设置,这个函数只能设置send和recv的超时,为了能够随意控制connect的超时时间,可以使用select。大致的过程就是先将socket设置成非阻塞,使用select去轮询套接口,再根据套接口去判断连接状态。
    先看以下代码:
int flag;
flag = fcntl(sock,F_GETFL,0);
flag |= O_NONBLOCK;
fcntl(sock,F_SETFL,flag);//设置非阻塞
if (type == SOCK_STREAM) {
int ret = -1;
connected = connect(sock, (struct sockaddr *) &address, 
sizeof(address));
if (connected != 0 ) {//if 1
if(errno != EINPROGRESS)
logdown(ERROR,"connect error :%s\n",strerror(errno));
else //esle
{
struct timeval tm;
tm.tv_sec = 3;
tm.tv_usec = 0;
fd_set set,rset;
FD_ZERO(&set);
FD_ZERO(&rset);
FD_SET(sock,&set);
FD_SET(sock,&rset);
socklen_t len;
int error = -1;
int res;
res = select(sock+1,&rset,&set,NULL,&tm);
if(res < 0)
{
logdown(WARNNING,"network error in connect\n");
ret =  -1;
}
else if(res == 0)
{
logdown(WARNNING,"connect time out\n");
ret = -2;
}
else if (1 == res)
if(FD_ISSET(sock,&set))
{
flag &= ~O_NONBLOCK;
fcntl(sock,F_SETFL,flag);//设置阻塞
return sock;
}
else
{
ret = -3;
logdown(WARNNING,"other error when select:%s\n",strerror(errno));
}
return ret;
}//else 
}//if 1
return sock;
}
程序先把socket设置成非阻塞,connect在非阻塞模式下会立刻返回,如果没有其他错误,返回值等于0。当connect不能立刻建立连接时,会返回一个EINPROGRESS,表示连接正在建立的过程中,这时我们可以使用select去轮询套接口,而select的轮询超时时间可以根据自己的需要去设置,最主要的是轮询的集合一定要是读和写的集合,即select的第二和第三个参数要赋值,待select返回就可以去判断返回值来确定connect的进程状态了。如果返回值小于0,说明connect的进程出现了错误,如果是等于0则说明connect超时,如果等于1,并且套接口此时的状态是可写,则说明了connect已经成功建立;( 设置等待时间,使用select函数等待正在后台连接的connect函数,这里需要说明的是使用select监听socket描述符是否可读或者可写,如果只可写,说明连接成功,可以进行下面的操作。如果描述符既可读又可写,分为两种情况,第一种情况是socket连接出现错误(不要问为什么,这是系统规定的,可读可写时候有可能是connect连接成功后远程主机断开了连接close(socket)),第二种情况是connect连接成功,socket读缓冲区得到了远程主机发送的数据。需要通过connect连接后返回给errno的值来进行判定,或者通过调用 getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len); 函数返回值来判断是否发生错误) 其他情况的话就算是其他错误吧,至此,我们只需要设置select的超时值就可以随心所欲地实现自己想要的connect连接超时了。
    最后,别忘了把套接口设置会阻塞状态,毕竟阻塞状态加线程方便控制。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在VS2010中,通过TCP/IP协议可实现双向连续通讯,下面介绍一个简单的实例。 首先,创建一个Winform应用程序,添加两个文本框和一个按钮,分别用来输入消息、显示接收到的消息以及连接服务器。在代码中,需要引入System.Net.Sockets和System.Threading命名空间。 接下来,创建一个TcpClient对象,并与指定的服务器建立连接。这里的IP地址和端口号需要根据实际情况填写。连接成功后,可以通过TcpClient对象的GetStream方法获取到网络流。 通过多线程机制,分别开启一个线程监听服务器的消息和一个线程发送消息。监听线程通过读取网络流中的字节数据,并将其转换成字符串进行显示。发送线程则通过写入网络流向服务器发送消息。这里需要注意的是,发送的消息需要自定义起始符和结束符,以供服务器端解析。 最后,建立发送按钮的事件处理程序,通过调用发送线程来发送消息。在退出应用程序时,需要关闭与服务器的连接,释放资源。 这个实例演示了如何使用TCP/IP协议在客户端与服务器之间进行双向连续通讯,可供初学者参考实践。 ### 回答2: 在VS2010中实现TCP/IP双向连续通讯的方法有很多,以下是一些简要的说明: 首先需要创建一个TCP服务器和客户端,然后建立连接。服务器可以通过Socket类中的Listen()和Accept()方法来实现。客户端可以使用Connect()方法来与服务器建立连接。 接下来,可以使用NetworkStream类来向对方发送和接收数据。这个类提供了Read()和Write()方法,可以用来实现双向数据传输。 在处理接收到的数据时,可以使用StreamReader类中的ReadLine()方法来读取接收到的字符串。同时,为了使数据能够及时传输,可以使用BufferedStream类来加速数据的传输。 最后,为了确保连接的可靠性,可以在程序中加入超时处理和异常处理的代码。 以上是一些简要的说明,实现TCP/IP双向连续通讯需要考虑的问题还有很多,需要开发者进行详细的分析和实践。 ### 回答3: Visual Studio 2010提供了许多实现TCP/IP双向连续通信的方法,其中之一是使用Socket类。以下是一个基本的例子,说明如何使用Socket类进行TCP/IP双向通讯。 1. 在VS2010中创建一个新的控制台应用程序,并在程序中添加以下名称空间: using System.Net.Sockets; using System.Text; 2. 创建一个TcpListener实例,用于监听指定端口上的传入连接。以下是示例代码: TcpListener listener = new TcpListener(IPAddress.Any, 8080); listener.Start(); 3. 创建一个TcpClient实例,用于连接到服务器。以下是示例代码: TcpClient client = new TcpClient(); client.Connect("127.0.0.1", 8080); 4. 在服务器端,启动一个循环来接受传入连接和消息。以下是示例代码: while (true) { TcpClient client = listener.AcceptTcpClient(); NetworkStream stream = client.GetStream(); byte[] buffer = new byte[1024]; int bytesRead = stream.Read(buffer, 0, buffer.Length); string message = Encoding.ASCII.GetString(buffer, 0, bytesRead); Console.WriteLine("Received: " + message); byte[] response = Encoding.ASCII.GetBytes("Response from server"); stream.Write(response, 0, response.Length); } 5. 在客户端,创建一个循环来向服务器发送消息和接收响应。以下是示例代码: TcpClient client = new TcpClient(); client.Connect("127.0.0.1", 8080); while (true) { NetworkStream stream = client.GetStream(); string message = Console.ReadLine(); byte[] buffer = Encoding.ASCII.GetBytes(message); stream.Write(buffer, 0, buffer.Length); buffer = new byte[1024]; int bytesRead = stream.Read(buffer, 0, buffer.Length); string response = Encoding.ASCII.GetString(buffer, 0, bytesRead); Console.WriteLine("Received: " + response); } 在这个例子中,服务器和客户端可以相互发送字符串消息。请注意,这只是一个起点,可以对不同的应用设置不同的监听器、客户端和协议来实现更强大的双向TCP/IP通讯。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值