C 使用带有随机端口的套接字将客户端绑定到服务器

C 使用带有随机端口的套接字将客户端绑定到服务器,c,C,我正在尝试在服务器和多个客户端之间创建聊天室。除了将套接字绑定到随机端口外,所有功能都正常工作。我通过创建一个随机端口 server\u info.sin\u port=htons(0); 我的问题在于客户端是否能够使用该端口,或者如何将端口号发送给客户端 如果我将端口替换为静态数字,如“8888”,程序将成功运行。我只是在客户端收集端口时遇到问题 服务器代码 intmain() { 信号(SIGINT、catch_ctrl_c_和_exit); //创建套接字 server\u sockfd

我正在尝试在服务器和多个客户端之间创建聊天室。除了将套接字绑定到随机端口外,所有功能都正常工作。我通过创建一个随机端口

server\u info.sin\u port=htons(0);
我的问题在于客户端是否能够使用该端口,或者如何将端口号发送给客户端

如果我将端口替换为静态数字,如“8888”,程序将成功运行。我只是在客户端收集端口时遇到问题

服务器代码

intmain()
{
信号(SIGINT、catch_ctrl_c_和_exit);
//创建套接字
server\u sockfd=socket(AF\u INET,SOCK\u STREAM,0);
如果(服务器\u sockfd==-1){
字符错误[255];
sprintf(错误,“无法创建套接字”);
写入(1,错误,strlen(错误));
退出(退出失败);
}
//套接字信息
服务器信息、客户端信息中的结构sockaddr\u;
int s_addrlen=sizeof(服务器信息);
int c_addrlen=sizeof(客户信息);
memset(&server\u info,0,s\u addrlen);
memset(和客户端信息,0,c地址);
server\u info.sin\u family=PF\u INET;
server\u info.sin\u addr.s\u addr=INADDR\u ANY;
//试验
server_info.sin_port=htons(0);
//捆绑并倾听
绑定(服务器\u sockfd,(结构sockaddr*)和服务器\u信息,s\u addrlen);
听(服务器_sockfd,5);
//打印服务器IP
字符开始[100];
getsockname(服务器\u sockfd,(结构sockaddr*)和服务器\u info,(socklen\u t*)和服务器\u addrlen);
sprintf(开始,“在%s:%d\n上启动服务器”,inet\u ntoa(服务器信息单地址),ntohs(服务器信息单端口));
写入(1,开始,strlen(开始));
//客户端的初始链接列表
root=newNode(server_sockfd,inet_ntoa(server_info.sin_addr));
现在=根;
而(1){
client_sockfd=accept(server_sockfd,(struct sockaddr*)和client_info,(socklen_t*)和c_addrlen);
//打印客户端IP
getpeername(客户端sockfd,(结构sockaddr*)和客户端信息,(socklen\u t*)和c\u addrlen);
字符客户端[255];
sprintf(客户端,“客户端%s:%d进来。\n”、inet\u ntoa(客户端信息.sin\u地址)、ntohs(客户端信息.sin\u端口));
写入(1,客户端,strlen(客户端));
//为客户端追加链接列表
ClientList*c=newNode(client_sockfd,inet_ntoa(client_info.sin_addr));
c->prev=现在;
现在->链接=c;
现在=c;
pthread_t id;
if(pthread_create(&id,NULL,(void*)客户端_处理程序,(void*)c)!=0){
perror(“创建pthread错误!\n”);
退出(退出失败);
}
}
返回0;
}
客户端代码

intmain()
{
信号(SIGINT、catch_ctrl_c_和_exit);
//命名
查尔尼克[255];
斯普林特(尼克,“请输入您的姓名:”);
写(1,尼克,斯特伦(尼克));
if(fgets(昵称、长度、名称、标准输入)!=NULL){
str_trim_lf(昵称、长度和名称);
}
if(strlen(昵称)<2 | | strlen(昵称)>=LENGTH_NAME-1){
char nameerr[100];
sprintf(nameerr,“\n名称必须多于一个字符,且少于三十个字符。\n”);
写(1,nameerr,strlen(nameerr));
退出(退出失败);
}
//创建套接字
sockfd=套接字(AF_INET,SOCK_STREAM,0);
如果(sockfd==-1){
字符错误[100];
sprintf(错误,“无法创建套接字”);
写(1,err,strlen(err));
退出(退出失败);
}
//套接字信息
服务器信息、客户端信息中的结构sockaddr\u;
int s_addrlen=sizeof(服务器信息);
int c_addrlen=sizeof(客户信息);
memset(&server\u info,0,s\u addrlen);
memset(和客户端信息,0,c地址);
server\u info.sin\u family=PF\u INET;
server_info.sin_addr.s_addr=inet_addr(“127.0.0.1”);
//试验
server_info.sin_port=htons(0);
//连接到服务器
int err=connect(sockfd,(结构sockaddr*)和服务器信息,s\u addrlen);
如果(错误==-1){
字符错误[100];
sprintf(错误,“连接到服务器错误!\n”);
写(1,err,strlen(err));
退出(退出失败);
}
//名字
getsockname(sockfd,(struct sockaddr*)和client_info,(socklen_t*)和c_addrlen);
getpeername(sockfd,(结构sockaddr*)和服务器信息,(socklen\u t*)和服务器地址);
char-conn[100];
char-ipval[100];
sprintf(conn,“连接到服务器:%s:%d\n”、inet\u ntoa(服务器信息单地址)、ntohs(服务器信息单端口));
sprintf(ipval,“您是:%s:%d\n”、inet_ntoa(客户端信息.sin_地址)、ntohs(客户端信息.sin_端口));
写(1,康涅狄格州,斯特伦(康涅狄格州));
写入(1,ipval,strlen(ipval));
发送(sockfd,昵称,长度\名称,0);
pthread\u t send\u msg\u thread;
if(pthread_create(&send_msg_thread,NULL,(void*)send_msg_handler,NULL)!=0){
字符错误[100];
sprintf(错误,“创建pthread错误!\n”);
写(1,err,strlen(err));
退出(退出失败);
}
pthread_t recv_msg_thread;
if(pthread_create(&recv_msg_thread,NULL,(void*)recv_msg_handler,NULL)!=0){
字符错误[100];
sprintf(错误,“创建pthread错误!\n”);
写(1,err,strlen(err));
退出(退出失败);
}
而(1){
国际单项体育联合会(旗){
查拜[20];
sprintf(再见,“\n您\n”);
写(1,拜拜,斯特伦(拜拜));
打破
}
}
关闭(sockfd);
返回0;
}
错误是由

connect(sockfd,(结构sockaddr*)和服务器信息,s\u addrlen);

您可以使用与发送服务器IP地址相同的方式向客户端发送端口号

为了通过TCP进行连接,客户端需要知道服务器的IP地址和非零端口号

如果客户端和服务器在同一台计算机上运行,通常使用文件、环境变量或剪贴板来传递IP地址和端口号

在您的示例中,可以将printf添加到server.c以打印IP地址和端口号(使用函数getsockname获取它们)。然后,您可以将代码添加到client.c以从
argv[1]