【问题标题】:How to completely destroy a socket connection in C如何在C中完全破坏套接字连接
【发布时间】:2012-05-24 02:22:43
【问题描述】:

我在 linux 中使用套接字创建了一个聊天客户端,我希望完全破坏连接。以下是代码的相关部分:

int sock, connected, bytes_recieved , true = 1, pid;  
char send_data [1024] , recv_data[1024];     
struct sockaddr_in server_addr,client_addr;    
int sin_size;
label:
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
    perror("Socket");
    exit(1);
}
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1)
{
    perror("Setsockopt");
    exit(1);
}
server_addr.sin_family = AF_INET;         
server_addr.sin_port = htons(3128);     
server_addr.sin_addr.s_addr = INADDR_ANY; 
bzero(&(server_addr.sin_zero),8); 
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1)
{
    perror("Unable to bind");
    exit(1);
}
if (listen(sock, 5) == -1)
{
    perror("Listen");
    exit(1);
}
printf("\nTCPServer Waiting for client on port 3128");
fflush(stdout);
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
//necessary code
close(sock);
goto label;

但是 close(sock) 似乎并没有完全关闭破坏连接,因为在转到“标签”之后,代码正在退出并显示错误消息

Unable to bind: Address already in use

那是连接不再发生。问题可能是什么?提前致谢。

编辑:我真正想要的是,当我在破坏连接后从头开始运行脚本时,它应该作为一个新程序运行。我该怎么做?

【问题讨论】:

  • 你为什么要这么做?您应该循环回到 accept 之前,而不是重新创建服务器套接字。
  • 为什么要关闭并重新打开监听套接字而不是循环accept()
  • 当我这样做时,我得到了回复You are connected to <ip>, <port> 这是我给检查连接是否建立的printf。仅当客户端运行程序时才应建立连接,但即使客户端没有在客户端运行程序也可以建立连接。我现在该怎么办?
  • "收到回复你连接到"---从哪里来?您的代码不包含该内容。请出示相关代码。

标签: c linux sockets network-programming


【解决方案1】:

好吧,因为当对方确认或在某个超时之后,连接才真正关闭。这是正常行为...

编辑:我实际上并没有检查您的代码,但是从其他用户的 cmets 中,您做错了什么......

【讨论】:

    【解决方案2】:

    您应该使用shutdown(2) 系统调用。

    【讨论】:

    • 我已经尝试过了,但仍然没有运气。连接没有被破坏。
    • 关闭前不需要。
    【解决方案3】:

    首先为命名,所以我们都给相同的东西起相同的名字:

    服务器端:

    套接字传递给listen(),然后传递给accept(),让我们调用监听套接字。 accept() 返回的套接字让我们调用 accepted 套接字。

    客户端:

    传递给connect()的套接字让我们调用connecting/connected套接字。


    关于你的问题:

    要终止accept()ed 连接关闭接受套接字(你称之为已连接),可选地首先使用shutdown(),然后使用close ()

    要在调用 accept() 之前立即接受新的连接循环,不要再次通过 bind()listen()

    如果您想摆脱在accept() 返回后发出的待处理 connect()s,请仅shutdown 和 关闭正在侦听 套接字。

    【讨论】:

    • 关闭前无需关机。关闭意味着关闭,除非 SD 与另一个进程共享,这里不是这种情况。而且你永远不需要关闭监听套接字。
    • @user207421:相应地修改了我的答案。
    【解决方案4】:

    连接仍然处于活动状态,因为您忘记关闭已连接的套接字。关闭监听套接字不会自动关闭连接的套接字。

    //necessary code
    close(connected);  // <---- add this line
    close(sock);
    goto label;
    

    我不确定您为什么要获得 EADDRINUSE。该代码在 linux 和 mac os 上运行良好。

    【讨论】:

      【解决方案5】:

      close 调用仅标记 TCP 套接字已关闭。它不再被进程使用。 但是内核可能仍会在一段时间内保留一些资源(TIME_WAIT、2MLS 等)。

      设置 SO_REUSEADDR 应该可以消除绑定问题。

      所以在调用setsockopt 时请确保true 的值确实非零(溢出错误可能会覆盖它):

      true = 1;
      setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int))
      

      pid 变量是您的代码。如果你使用fork(用于启动连接处理进程),那么你也应该在不需要它的进程中关闭sock

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-18
        • 1970-01-01
        • 1970-01-01
        • 2013-12-12
        • 1970-01-01
        相关资源
        最近更新 更多