gpt4 book ai didi

c - 在用 C 实现的多客户端单服务器程序中识别来自客户端的消息

转载 作者:太空宇宙 更新时间:2023-11-04 08:54:59 26 4
gpt4 key购买 nike

我是网络初学者。我使用 C 中的套接字实现了一个多客户端单服务器程序。如果我运行服务器和客户端的两个或多个实例,那么我如何识别向服务器发送消息的客户端。这个实现是否正确,还是我必须修改它?

    //server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<unistd.h>
#define MAX 1000

void serveClient(int sock)
{
int r;
char buffer[MAX];
do
{
bzero(buffer, sizeof(buffer));
r = read(sock, buffer, sizeof(buffer));
if(strcasecmp(buffer,"bye")==0) return;
if(r != 0)
printf("\nMessage from client : %s\n",buffer);
}while(1);
}

int main()
{
int sockfd, newfd, len, r, pid;
char buff[MAX];
struct sockaddr_in servaddr,cliaddr;

//creating socket
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
exit(1);
}
else
printf("\nSocket created\n");

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(7790);
servaddr.sin_addr.s_addr = INADDR_ANY;

//bnding a name to socket
if(bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
{
perror("bind");
exit(1);
}
else
printf("\nBind successful\n");

//listening for connections
if(listen(sockfd, 5) < 0)
{
perror("listen");
exit(1);
}
else
printf("\nListening...\n");

//accepting a connection
do
{
len = sizeof(cliaddr);
if((newfd = accept(sockfd, (struct sockaddr*)&cliaddr, &len)) < 0)
{
perror("accept");
exit(1);
}
else
printf("\nNew connection accepted\n");

pid = fork();
if(pid == -1)
{
perror("fork");
close(newfd);
continue;
}
else if(pid == 0)
{
serveClient(newfd);
close(newfd);
printf("\nClient terminated\n\nWaiting for new client...\n");
}
else
{
close(newfd);
}
}while(1);
close(sockfd);
return 0;
}


//client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include<stdlib.h>
#define MAX 1000

int main(int argc, char *argv[])
{
int len, sockfd, n;
char buff[MAX];
; struct sockaddr_in servaddr, cliaddr;
if(argc == 2)
{
//creating socket
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
exit(1);
}
else
printf("\nSocket created\n");

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(7790);
servaddr.sin_addr.s_addr = inet_addr(argv[1]);

//initiating connection on the socket
if(connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
{
perror("connect");
exit(1);
}
else
printf("\nConnected\n");

//sending message
printf("\nType \"bye\" to disconnect\n");
do
{
printf("\nMessage : ");
scanf("%s",buff);
n = write(sockfd, buff, sizeof(buff));
if(strcasecmp(buff, "bye") == 0) exit(0);
}while(1);
close(sockfd);
}
else
{
printf("\nSpecify an IP address\n");
exit(1);
}
return 0;
}

最佳答案

有很多书说,当您在基于 unix 的操作系统上拥有服务器客户端架构时,让操作系统完成所有艰苦的工作。当他们这样说时,他们的意思是让您的主线程监听客户端的套接字。当客户端进来时,接受 hte 连接并将使用 accept 创建的新套接字 fork 到新线程/进程(使用线程,实际上不是进程,所以不要使用 fork,而是使用 pthreads)。然后让这个线程处理那个客户端,您可以根据为它们提供服务的线程来区分客户端。

您似乎在执行 fork 实现。虽然这看起来是个好主意,但请记住,除非您使用 exec 重新加载程序镜像,否则您的 child 将拥有与您的 parent 相同的内存占用。使用线程是一个更好的主意,这样您只有一个程序镜像,并且每个客户端连接的开销更少。您可以通过让线程池等待信号量,然后在连接时释放一个来创建更少的开销。将您接受的新文件描述符保存在一个您可以跟踪的数组中。如果你用完了线程,你可以让一个线程处理多个客户端,或者只创建另一个线程来处理涌入的线程!然后你可以稍后销毁它们。

您也可以只创建包含客户端数据的通信协议(protocol),这样您就可以知道谁在说什么。唯一的问题是您必须扫描每个数据包以找出它属于哪个客户端,并存储它直到您获得整个消息(如果它不能全部放入一个数据包中)。使用 accept、hand off 的 pthread 模型更容易。这样,您就可以通过线程的 threadid 来识别每个客户端。

关于c - 在用 C 实现的多客户端单服务器程序中识别来自客户端的消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17656306/

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