gpt4 book ai didi

c - 尝试在关闭旧套接字后使用新套接字,但没有成功

转载 作者:行者123 更新时间:2023-11-30 18:46:27 26 4
gpt4 key购买 nike

对于类作业,我必须在客户端发送“NEWPORT”后关闭所有打开的套接字并将“n端口”分配给新套接字,从那一刻起我必须使用为新传入连接创建的套接字,但是当我尝试连接到新的连接时,客户端的 perror 函数告诉我“连接被拒绝”。

服务器代码

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

#define MAX_SIZE 512

void manage_connections(int fds,struct sockaddr_in serv_addr, struct sockaddr_in cl_addr, socklen_t cl_len);

int main(int argc, char* argv[]){
struct sockaddr_in serv_addr, cl_addr;
socklen_t cl_len;
int fds=0;

serv_addr.sin_family = AF_INET;

serv_addr.sin_port = htons(5200);

serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

fds = socket(AF_INET, SOCK_STREAM, 0);

if(fds<0){

perror("Socket error");

exit(-1);

}

if(bind(fds,(struct sockaddr*)&serv_addr, sizeof(serv_addr))<0){

perror("Bind error");

exit(-1);

}

if((listen(fds,5))<0){

perror("Listen error");

exit(-1);

}

manage_connections(fds,serv_addr, cl_addr, cl_len);

close(fds);

return 0;

}

void manage_connections(int fds,struct sockaddr_in serv_addr, struct sockaddr_in cl_addr, socklen_t cl_len){

char buffer[MAX_SIZE], cl_ip[MAX_SIZE], cl_port[MAX_SIZE], cmd_np[MAX_SIZE], cmd_np_n[MAX_SIZE], cmd_np_str[MAX_SIZE], nport[MAX_SIZE];

int i=0, port=0,fdc=0, nfds;

struct sockaddr_in nserv_addr;

while(1){

cl_len = sizeof(cl_addr);

fdc = accept(fds, (struct sockaddr*)&cl_addr, &cl_len);

if(fdc<0){

perror("Accept error");

exit(-1);

}

do{

for(i=0;i<MAX_SIZE;i++){

buffer[i]=0;

cl_ip[i]=0;

cl_port[i]=0;

cmd_np[i]=0;

cmd_np_n[i]=0;

cmd_np_str[i]=0;

nport[i]=0;

}

read(fdc,buffer, MAX_SIZE);

if(strcmp(buffer,"MYIP")==0){

strcat(cl_ip,inet_ntoa(cl_addr.sin_addr));

write(fdc,cl_ip,strlen(cl_ip));

} else if(strcmp(buffer,"MYPORT")==0){

sprintf(cl_port,"%d", (int)htons(cl_addr.sin_port));

write(fdc, cl_port, strlen(cl_port));

}else{

sscanf(buffer, "%s %d", cmd_np, &port);

sprintf(nport, "%d", port);

if(strcmp(cmd_np,"NEWPORT")==0){

strcat(cmd_np_str, "ACK ");

strcat(cmd_np_str, nport);

write(fdc, cmd_np_str,strlen(cmd_np_str));

close(fds);

close(fdc);

nserv_addr.sin_family=AF_INET;

nserv_addr.sin_port = htons(port);

nserv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

nfds = socket(AF_INET, SOCK_STREAM,0);

if(nfds<0){

perror("New socket error");

exit(-1);

}

if((bind(nfds,(struct sockaddr*)&nserv_addr,sizeof(nserv_addr)))<0){

perror("New bind error");

exit(-1);

}

if((listen(nfds,5))<0){

perror("New listen error");

exit(-1);

}

manage_connections(nfds,nserv_addr, cl_addr, cl_len);

}

}

}while(strcmp(cmd_np,"NEWPORT")!=0);

close(fdc);

}


}

客户端代码

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

#define MAX_SIZE 512

int main(int argc, char* argv[]){
struct sockaddr_in cl_addr;
int fdc=0,len=0, res_len=0,i=0;
char buffer[MAX_SIZE];

cl_addr.sin_family = AF_INET;

cl_addr.sin_port = htons(5200);

inet_aton("192.168.10.128",&cl_addr.sin_addr);

fdc = socket(AF_INET, SOCK_STREAM,0);

if(fdc<0){

perror("Accept error");

exit(-1);

}

if((connect(fdc, (struct sockaddr*)&cl_addr, sizeof(cl_addr)))<0){

perror("Connect error");

exit(-1);

}

while(1){

write(1, "Inserire uno tra i comandi MYIP, MYPORT, NEWPORT:\n", strlen("Inserire uno tra i comandi MYIP, MYPORT, NEWPORT:\n"));

len = read(1, buffer, MAX_SIZE);

buffer[len-1] = '\0';

write(fdc, buffer, strlen(buffer)+1);

for(i=0;i<MAX_SIZE;i++)

buffer[i]=0;

res_len = read(fdc,buffer,MAX_SIZE);

write(1,"\nResponso: ",strlen("\nResponso: "));

write(1, buffer, res_len);

write(1,"\n",strlen("\n"));

}

close(fdc);

return 0;
}

最佳答案

您的客户端被硬编码为 5200 端口号。如果您使用 NEWPORT 将服务器切换到新服务器,则服务器将不再监听 5200,因为您关闭了原始监听套接字并打开了一个新监听套接字。

因此,当您再次运行客户端时,它会被拒绝连接因为现在没有人在监听您正在连接的套接字。

我看到的最好的解决方法是添加在客户端将端口号指定为命令行参数的功能。

代码的其他问题:

  1. 您假设您将在每次调用write时发送整个缓冲区内容,并且您将在每次read时接收整个缓冲区内容。在像这样的玩具程序中,这可以工作,但 TCP 不能保证。

  2. 您的manage_connections函数是递归的,这看起来是一个很糟糕的结构。调用次数足够多,您就会耗尽堆栈。

  3. 没有内置的方法可以退出客户端程序。您可以按 Ctrl-C 中止,但在 NEWPORT 情况下,它不会检测到服务器刚刚关闭了连接(因为它正在从终端读取)。

  4. 您实际上是从标准输出文件读取。如果您连接到终端,这通常可以工作,但在其他情况下则不起作用,并且不是一个值得依赖的好东西。

  5. 您将 cl_addrcl_len 变量传递到 manage_connections 中,但这毫无意义。调用者不会在调用之前初始化它们或在调用之后使用它们。它们应该只在函数内部声明。

关于c - 尝试在关闭旧套接字后使用新套接字,但没有成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51562796/

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