在Windows下connect到服务端,怎么控制连接超时?

A:

 connect()目的主机可达,但目的端口不可达,函数会立即出错返回。
但要是目的主机不可达,函数会等待一段时间出错返回,请问这个超
时时间如何在程序里设置?

Q:

可以设置超时机制
使用此函数前,需先将socket设置为非锁定模式,这样,在connect时,才会立马跳过,同时,通常也会产生一个WSAEWOULDBLOCK错误,这个错误没关系。再执行select则是真正的超时。

WSADATA wsd;
SOCKET cClient;
int ret;
struct sockaddr_in server;
hostent *host=NULL;

if(WSAStartup(MAKEWORD(2,0),&wsd)){return 0;}
cClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(cClient==INVALID_SOCKET){return 0;}
//set Recv and Send time out
int TimeOut=6000; //设置发送超时6秒
if(::setsockopt(cClient,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
return 0;
}
TimeOut=6000;//设置接收超时6秒
if(::setsockopt(cClient,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
return 0;
}
//设置非阻塞方式连接
unsigned long ul = 1;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);
if(ret==SOCKET_ERROR)return 0;

//连接
server.sin_family = AF_INET;
server.sin_port = htons(25);
server.sin_addr .s_addr = inet_addr((LPCSTR)pSmtp);
if(server.sin_addr.s_addr == INADDR_NONE){return 0;}

connect(cClient,(const struct sockaddr *)&server,sizeof(server));

//select 模型,即设置超时
struct timeval timeout ;
fd_set r;

FD_ZERO(&r);
FD_SET(cClient, &r);
timeout.tv_sec = 15; //连接超时15秒
timeout.tv_usec =0;
ret = select(0, 0, &r, 0, &timeout);
if ( ret <= 0 )
{
::closesocket(cClient);
return 0;
}
//一般非锁定模式套接比较难控制,可以根据实际情况考虑 再设回阻塞模式
unsigned long ul1= 0 ;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul1);
if(ret==SOCKET_ERROR){
::closesocket (cClient);
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个基于Java的客户端服务端的心跳包、客户端断线重连和服务端超时断开客户端连接的示例: 服务器端代码: ```java import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class Server { private static final int TIMEOUT = 5000; // 5秒超时 public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server started, waiting for client..."); while (true) { Socket socket = serverSocket.accept(); System.out.println("Client connected."); socket.setSoTimeout(TIMEOUT); // 设置超时时间 InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); byte[] buffer = new byte[1024]; int len; while (true) { try { len = inputStream.read(buffer); if (len > 0) { String message = new String(buffer, 0, len); System.out.println("Received message from client: " + message); outputStream.write(message.getBytes()); } } catch (IOException e) { System.out.println("Client disconnected."); socket.close(); break; } } } } } ``` 客户端代码: ```java import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.SocketException; import java.util.Scanner; public class Client { private static final int HEARTBEAT_INTERVAL = 2000; // 2秒心跳包发送间隔 private static final int RECONNECT_INTERVAL = 5000; // 5秒重连间隔 private static final int TIMEOUT = 10000; // 10秒超时 public static void main(String[] args) throws IOException { String serverHost = "localhost"; int serverPort = 8888; Socket socket = null; InputStream inputStream = null; OutputStream outputStream = null; Scanner scanner = new Scanner(System.in); while (true) { try { socket = new Socket(serverHost, serverPort); System.out.println("Connected to server."); inputStream = socket.getInputStream(); outputStream = socket.getOutputStream(); socket.setSoTimeout(TIMEOUT); // 设置超时时间 // 发送心跳包 Thread heartbeatThread = new Thread(() -> { try { while (true) { outputStream.write("Heartbeat".getBytes()); Thread.sleep(HEARTBEAT_INTERVAL); } } catch (Exception e) { // 心跳包发送失败,说明连接已断开,退出线程 } }); heartbeatThread.start(); // 接收消息 byte[] buffer = new byte[1024]; int len; while (true) { try { len = inputStream.read(buffer); if (len > 0) { String message = new String(buffer, 0, len); System.out.println("Received message from server: " + message); } } catch (SocketException e) { // 超时连接断开,退出循环 System.out.println("Server disconnected."); break; } } // 关闭心跳包线程 heartbeatThread.interrupt(); try { heartbeatThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } // 关闭连接和流 socket.close(); inputStream.close(); outputStream.close(); // 等待一段时间后重连 Thread.sleep(RECONNECT_INTERVAL); } catch (IOException e) { // 连接失败,等待一段时间后重连 System.out.println("Failed to connect to server."); try { Thread.sleep(RECONNECT_INTERVAL); } catch (InterruptedException ex) { ex.printStackTrace(); } } } } } ``` 这个例子实现了心跳包发送、客户端断线重连和服务端超时断开客户端连接的功能。客户端会在连接断开后自动重连,服务端会在客户端超时或断开连接后关闭连接。你可以根据自己的需求进行修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值