Linux 如何完全破坏C中的套接字连接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10619952/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 06:21:35  来源:igfitidea点击:

How to completely destroy a socket connection in C

clinuxsocketsnetwork-programming

提问by Harikrishnan

I have made a chat client in linux using socket, and i wish to destroy the connection completely. Following is the relevant portions of the code:

我已经使用套接字在 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;

but the close(sock) doesnot seem to close the destroy the connection completely, because after going to 'label' the code is exiting showing the error message

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

Unable to bind: Address already in use

That is the connection is not happening again. What can the problem be? Thanks in advance.

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

EDIT: What I actually want is, when I run the script from the beginning after destroying the connection, it should run as a fresh program. How can I do it?

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

采纳答案by SKi

The closecall only marks the TCP socket closed. It is not usable by process anymore. But kernel may still hold some resources for a period (TIME_WAIT, 2MLS etc stuff).

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

Setting of SO_REUSEADDR should remove binding problems.

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

So be sure that value of trueis really non-zero when calling setsockopt(overflow bug may overwrite it):

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

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

There is pidvariable is your code. If you use fork(for starting connection handling processs), then you should close sockalso in the process which does not need it.

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

回答by Malkocoglu

Well, because a connection is really closed when the other party acknowledges it or after a certain timeout. This is normal behaviour...

好吧,因为当另一方确认连接时或在某个超时之后,连接实际上已关闭。这是正常行为...

EDIT: I did not actually check your code but from other users' comments, you are doing something wrong...

编辑:我实际上并没有检查你的代码,但从其他用户的评论来看,你做错了什么......

回答by Basile Starynkevitch

You should use the shutdown(2)system call.

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

回答by alk

First for the naming, so we all name the same things the same:

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

Server side:

服务器端:

The socket passed to listen()and then to accept()let's call the listeningsocket. The socket returned by accept()let's call the acceptedsocket.

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

Client side:

客户端:

The socket passed to connect()let's call the connecting/connectedsocket.

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



Regarding your issue:

关于你的问题:

To terminate the accept()ed connection close the acceptedsocket(what you call connected) by optionally first using shutdown()followed by close ().

要终止accept()编辑连接紧密的接受插槽通过可选首先使用(你叫什么连接),shutdown()其次是close ()

To then accept a new connection loop right back before the call to accept(), do notgo via bind()and listen()again.

然后,为了接受呼叫之前一个新的连接环右后卫accept()通过走bind()listen()试。

Only shutdown andclose the listeningsocket if you want to get rid of pendingconnect()s issued after accept()returned.

如果您想摆脱返回后发出的挂起s,则仅关闭并关闭侦听套接字。connect()accept()

回答by enobufs

The connection is still active because you forgot to close the connected socket. Closing the listening socket does not automatically close the connected socket.

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

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

I am not sure though why you are getting EADDRINUSE. The code worked fine on both linux and mac os.

我不确定你为什么会得到 EADDRINUSE。该代码在 linux 和 mac os 上运行良好。