0

我有这个代码。(在我的其他旧项目中使用它,效果很好)

SOCKET Connect(char * host, int port){
   struct sockaddr_in sin = {0}; 
   struct hostent * entry = 0;

   SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if(s == INVALID_SOCKET){
    return INVALID_SOCKET;
} 

entry = gethostbyname(host);

if(entry == 0){
   closesocket(s);
    return INVALID_SOCKET;
}

sin.sin_addr   = *((LPIN_ADDR)*entry->h_addr_list);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);

// The process becomes dealocked after this line
if( connect(s,(const LPSOCKADDR)&sin,sizeof(SOCKADDR)) == SOCKET_ERROR){
    closesocket(s);
    return INVALID_SOCKET;
}

return s;
}

我今天早上开始使用 TTcpClient 和 Indy 的 TIdTcpClient 包装器处理 Delphi 项目,我注意到该过程没有建立任何连接,而是在调用 connect 后挂起。然后我切换到 C/C++ 并尝试使用这个做同样事情的代码。在它挂起之后,就没有办法杀死它了(除非在调试它时我不得不退出调试器)。TaskManager,Process Explorer 没有做任何事情。

没有线程或循环或任何可能导致它挂起的代码和另一个在连接后写入套接字的函数。

使用 Visual Studio 进行调试时,一段时间后会出现一条消息(如下)

Visual Studio 错误

甚至 Wireshark 也没有显示任何内容。重新启动我的电脑,仍然是同样的问题。

那么以前有人遇到过这个问题吗?

使用的编译器

  • 视觉工作室 2010
  • 佩莱斯-C
  • 德尔福 7

操作系统:Windows 7 64 位,旗舰版

温索克版本:2.2

更新:

所以我想我会逃跑并切换到Java,只是在几次之后才发现同样的问题。这到底是怎么回事。即使在 localhost 上,Java 也需要大约 2 分钟才能连接。这个简单的代码需要大约 2 分钟,在此期间 java.exe 也无法被杀死。

long startTime = System.currentTimeMillis(), endTime;
Socket clientSock = new Socket("localhost",80); // running Apache on localhost
endTime = System.currentTimeMillis();
Log("Connection time " + (endTime - startTime) + " ms");
clientSock.close();

run:
Connection time 125088 ms 

至于 Java,我做了一些搜索,这个问题是 JDK 版本 1 中的一个错误,但更改日志显示它已被修补。但是这又发生在底层的winsock库中。为什么 ?这个程序立即连接,它也使用了winsock: http: //flatassembler.net/examples/quetannon.zip

所以现在我不得不重写976行JAVA汇编就因为这个?帮帮我这里的人。

4

2 回答 2

0

由于您在最终委托给 Winsock 的多个包装器中遇到相同的问题,因此可以安全地假设这是一个操作系统问题,而不是编码问题。您的系统上的某些东西已经破坏了您的 Winsock 安装,或者操作系统通常存在网络问题,特别是因为简单的操作系统重新启动并没有解决问题。尝试使用 Windows 的命令行netsh工具来重置 TCP 和 Winsock 子系统,该命令行ipconfig工具用于刷新 DNS 缓存,重新启动,然后查看问题是否仍然存在。

在编码方面,您应该在 上实现超时connect()以避免进一步的死锁。有两种方法可以做到这一点:

  1. 将套接字置于非阻塞模式,然后调用select()ifconnect()返回WSAEWOULDBLOCk错误。如果select()超时,关闭套接字。

  2. 让套接字处于阻塞模式并使用单独的线程来管理超时。调用connect()线程,或者在线程中运行你的超时逻辑,这并不重要,但如果超时时间connect()仍在运行,那么你可以关闭套接字, aborting connect()。这是TIdTCPClient使用的方法。

于 2013-07-09T15:53:16.160 回答
0

好的。对于 JAVA 部分,至少我根据此处的答案使用以下代码解决了它Java Socket creation requires more time

所以基本上默认的超时值(可能)很大。所以我所做的就是设置一个 3 秒的超时,然后一旦抛出超时异常,下一个调用就会立即生效。

private static final int CONNECT_TIMEOUT = 3000; // 3 seconds
private static Socket AttemptConnection(String host, int port) {
    Socket temp;
    try {
        temp = new Socket();
        temp.connect(new InetSocketAddress(host, port), CONNECT_TIMEOUT);
        return temp;
    } catch (Exception ex) {
        temp = null;
        lastException = ex.getMessage();
        return temp;
    }
}

在你的代码中的某个地方(至少在我的应用程序中)

while ( (clientSock = AttemptConnection("localhost",80)) == null ){
    Log("Attempting connection. Last exception: " + lastException);
    try{Thread.sleep(2500);}catch(Exception ex){} /* This is necessary in my application */
}

所以看着这个,我认为对所有套接字实现(JAVA、Delphi 等)的修复是设置一个小的超时值,然后再次连接。

编辑

问题的根源找到了:我的笔记本电脑上运行了一个 HIPS 程序(COMODO 防火墙)。如果 COMODO 的 cmdagent.exe 处于活动状态,它会向我显示我可以接受/拒绝的传出连接的警报。如果没有,它会默默地拒绝连接,因此某些东西在低级别陷入僵局。我担心我的电脑被弄坏了。

于 2013-07-25T03:38:38.287 回答