gpt4 book ai didi

c - 使用c中的套接字处理多个客户端双向通信

转载 作者:行者123 更新时间:2023-11-30 17:26:07 24 4
gpt4 key购买 nike

这是我第一次用c语言构建一个接受多个客户端的服务器,我需要使用select来实现这一点。

我目前能够向服务器发送信息,但是当服务器发回时,信息最终会触发服务器端的 select 语句,而不是实际发送到客户端。请帮忙:(

客户:

sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sockfd < 0) syserr("can't open socket");
printf("create socket...\n");

memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr = *((struct in_addr*)server->h_addr);
serv_addr.sin_port = htons(portno);

if(connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
syserr("can't connect to server");
printf("connect...\n");

// send the server our username
n = (int) send(sockfd, argv[3], strlen(argv[3]), 0) ;
if(n < 0) syserr("Can't send username to server\n");
printf("Username sent to server\n");

// wait for response, n ALWAYS RETURNS 0
n = (int) recv(sockfd, buffer, strlen(buffer), 0);

printf("buffer:\n%s\n",buffer) ;
if(n < 0) syserr("Can't receive from server\n");
else if (n == 0)
{
close(sockfd) ;
syserr("Server disconnected you due to duplicate username.\n") ;
}
else buffer[n] = '\0';



while ( done == 0 )
{
// rest of program loop, not being reached yet
}

close(sockfd);
return 0;

服务器:

portno = atoi(argv[1]);

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) syserr("can't open socket");
printf("create socket...\n");

memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
syserr("can't bind");
printf("bind socket to port %d...\n", portno);

listen(sockfd, 5);

FD_ZERO(&fds) ;
FD_SET(sockfd, &fds) ;

for(;;)
{
printf("wait on port %d...\n", portno);
addrlen = sizeof(clt_addr);
//newsockfd = accept(sockfd, (struct sockaddr*)&clt_addr, &addrlen);
//if(newsockfd < 0) syserr("can't accept");

readfds = fds ;
int result = select(FD_SETSIZE, &readfds, NULL, NULL, NULL) ;

// no timeout val, so never 0 return
if(result == -1)
syserr("Error on select call.\n") ;

int i ;
for( i = 0; i < FD_SETSIZE; i++ ) // loop through set of fds
{
if (FD_ISSET(i, &readfds)) // if fd i has data available to be read
{
if (i == sockfd) // if we are reading from server fd
{
if (numClients < maxClients) // if we could fit more clients
{
// place incoming client's fd into array of all clients
clients[numClients].clientfd = accept(sockfd, (struct sockaddr*)&clt_addr, &addrlen);
if(clients[numClients].clientfd < 0) syserr("Error on accept.\n");

FD_SET(clients[numClients].clientfd, &fds) ;

// receive the username sent by user
printf("new incoming connection, block on receive\n");
n = (int) recv(clients[numClients].clientfd, clients[numClients].username, 30, 0);
if(n < 0) syserr("can't receive from client");

clients[numClients].username[n] = '\0';

printf("New user accepted: %s\n", clients[numClients].username) ;
clients[numClients].online = 1 ;

// NOW I NEED TO SEND SOME INFO BACK
/// THIS IS THE PART THAT IS NOT SENDING BACK PROPERLY
/// IT IS ACTUALLY TRIGERRING THE SELECT ON THE SECOND ITERATION
n = (int) send(clients[numClients].clientfd, "Hey\nThis\nis\na\ntest", 18, 0) ;
if(n < 0) syserr("Can't send userlist to client.\n");
printf("n: %d\n", n) ; // My print returns the expected 18
printf("User List sent to client.\n") ; // This also prints

++numClients ; // extend client counter
}
else
{
printf("Sorry, we are full.\n") ;
}
}
else // not server file descriptor
{
/// On my second iteration This is triggered through the ‘select’ because of my send back above

// check if recv returns 0 for disconnect
n = (int) recv(clients[i].clientfd, buffer, sizeof(buffer), 0);
if(n < 0) syserr("can't receive from client"); // I actually get an error for bad fd

if( n == 0 ) // disconnected
{
// This code not reached yet
}
else // A message is being sent
{
// This code not reached yet
}
}
}
}
}
close(sockfd);
return 0;

最佳答案

我看不到你如何在客户端中声明buffer,但我可以看到你这样使用它:

n = (int) recv(sockfd, buffer, strlen(buffer), 0);

如果 buffer 中的第一个字符为 0,则 strlen(buffer)0n > 永远是 0。

如果您有char buffer[...];,只需使用:

n = (int) recv(sockfd, buffer, sizeof(buffer), 0);

如果在堆栈上使用动态分配:buffer = (char *) malloc(size);,请执行以下操作:

n = (int) recv(sockfd, buffer, size, 0);

关于c - 使用c中的套接字处理多个客户端双向通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26873490/

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