gpt4 book ai didi

c - 如何避免服务器套接字出现 TIME_WAIT?

转载 作者:IT王子 更新时间:2023-10-29 01:09:01 27 4
gpt4 key购买 nike

<分区>

我知道您会将其掩盖为重复项(question1question2question3),但答案不是我要找的(我认为其他人也是)。
所以,我指的是套接字大师(我爱你们):如果我关闭套接字,我怎么会得到绑定(bind)错误(地址已经在使用中)?
我将描述我的问题。

I've got a client that communicate with a server
In the server, I have two sockets: sockS (the main socket, that listens) and sockTX (the client one)
If I call my programs once, the communication is fine, then I close both sockets
If I recall server and client, I get the error and I've to wait the TIME_WAIT (~3 minutes seconds on Ubuntu 32bit)

为什么在关闭两个 套接字后我仍然遇到绑定(bind)错误?
有没有办法让它在没有任何魔法的情况下工作(SO_REUSEADDR)?
我知道我的代码有问题...

谢谢大家。

这就是代码:
客户端

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 5000
#define SERVER "127.0.0.1"
#define MAXLINE 128

int printMessage(char* str);

int main(){
char buff[MAXLINE+1];

struct sockaddr_in server, client;
struct hostent *host;
int sock, n;
//socklen_t len;

if((sock = socket(AF_INET,SOCK_STREAM,0)) == -1){
perror("\nErrore socket()");
return -1;
}

client.sin_family = AF_INET;
client.sin_port = htons(0); // la porta e' scelta dal sistema operativo
client.sin_addr.s_addr = htonl(INADDR_ANY);

if( bind(sock,(struct sockaddr*)&client, sizeof(client)) == -1){
perror("\nErrore bind()");
return -1;
}

server.sin_family = AF_INET;
server.sin_port = htons(PORT);

if((host = gethostbyname(SERVER)) == NULL ){
perror("\nErrore gethostbyname()");
return -1;
}

server.sin_addr = *((struct in_addr *)host->h_addr);

if(connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0){
perror("\nErrore connect");
return -1;
}

// MESSAGGIO

sprintf(buff, "CTX\nclientTX\nserver\nCiao da client\n");
if(send(sock, buff, strlen(buff), 0) < 0) {
perror("\nErrore sendto");
return -1;
}
else {
printf("\nMessaggio inviato");
}

if((n = recv(sock, buff, MAXLINE, 0)) < 0) {
perror("\nErrore ricezione risposta");
return -1;
} else {
buff[n] = '\0';
int test = printMessage(buff);
printf("\nEsito: %s\n", (test == 1 ? "OK" : "FAIL"));
}

shutdown(sock, 2); // 2 = RD_WR
close(sock);
return 0;
}

int printMessage(char* str){
int i;
char* temp;

printf("Mittente: ");
for(i = 0; str[i] != '\n'; i++)
printf("%c", str[i]);
printf(" ");
for(i = i+1; str[i] != '\n'; i++)
printf("%c", str[i]);
printf("\nDestinatario: ");
for(i = i+1; str[i] != '\n'; i++)
printf("%c", str[i]);

temp = (char*)malloc(30 * sizeof(char));
strncpy(temp, str+i+1, 30);
printf("Messaggio: %s\n", temp);

if(strcmp(temp, "OK") == 0)
return 1;
else
return 0;
}


服务器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 5000
#define SERVER "127.0.0.1"
#define MAXLINE 128

int printMessage(char* str);

int main() {
char buff[MAXLINE+1];
struct sockaddr_in server; //, client;
int sockS, sockTX, n;

if((sockS = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror("\nErrore socket()");
return -1;
}

server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(sockS, (struct sockaddr *)&server, sizeof(server)) == -1)
{
perror("\nErrore bind()");
return -1;
}

if(listen(sockS, 10) == -1)
{
perror("\nErrore listen()");
return -1;
}
printf("SERVER\nInizializzazione completata!\n");

if((sockTX = accept(sockS, (struct sockaddr *)NULL, NULL)) == -1)
{
perror("\nErrore accept()");
return -1;
}
printf("Socket connesso\n");

// INVIO
if((n = recv(sockTX, buff, MAXLINE, 0)) < 0) {
perror("\nErrore recv()");
return -1; // BREAK??

} else {
buff[n] = '\0';
printMessage(buff);

}

sprintf(buff, "S\nserver\nclientTX\nOK\n");
if(send(sockTX, buff, strlen(buff), 0) < 0){
perror("\nErrore send()");
return -1; // BREAK??

} else {
printf("Risposta inviata\n");

}

shutdown(sockTX, 2);
close(sockTX);

shutdown(sockS, 2);
close(sockS);
return 0;
}

int printMessage(char* str){
int i;
char* temp;

printf("Mittente: ");
for(i = 0; str[i] != '\n'; i++)
printf("%c", str[i]);
printf(" ");
for(i = i+1; str[i] != '\n'; i++)
printf("%c", str[i]);
printf("\nDestinatario: ");
for(i = i+1; str[i] != '\n'; i++)
printf("%c", str[i]);

temp = (char*)malloc(30 * sizeof(char));
strncpy(temp, str+i+1, 30);
printf("Messaggio: %s\n", temp);

if(strcmp(temp, "OK\n") == 0)
return 1;
else
return 0;
}

谢谢大家

编辑 1:可能的解决方案(不是很漂亮,但比 SOCK_REUSEADDR 多一点)
尝试在关闭和关闭两个服务器的套接字之前添加一个 sleep (1)。
客户端将在服务器之前关闭并且它会工作
不是很漂亮,我知道。

或者,更好的是,在关闭服务器内的第一个套接字之前,您可以检查客户端是否关闭了连接(如 here )

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com