gpt4 book ai didi

c - C语言多客户端服务器通信程序如何同时使用writefds和readfds?

转载 作者:太空宇宙 更新时间:2023-11-04 10:03:36 25 4
gpt4 key购买 nike

我目前正在尝试创建一个多客户端服务器,使服务器能够用 C 语言执行读取和写入功能。我能够使用 readfds 从客户端读取数据并将其作为参数放入 SELECT 中。当我添加 writefds 时,客户端无法连接到服务器。我不确定背后的问题是什么,这是否是传输和接收数据的正确方法

这是我服务器的代码

#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h>
#include <errno.h>
#include <unistd.h> //close
#include <arpa/inet.h> //close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h> //FD_SET, FD_ISSET, FD_ZERO macros

#define TRUE 1
#define FALSE 0
#define PORT 8080

int main(int argc , char *argv[])
{
int opt = TRUE;
int master_socket , addrlen , new_socket , client_socket[30] ,
max_clients = 2 , activity, i , valread , sd;
int max_sd;
struct sockaddr_in address;

char buffer[1025]; //data buffer of 1K

fd_set readfds;
fd_set writefds;


char *message = "Welcome to Server\r\n";

//initialise all client_socket[] to 0 so not checked
for (i = 0; i < max_clients; i++)
{
//client_socket[i] = 0;
}

//create a master socket
if( (master_socket = socket(AF_INET , SOCK_STREAM , 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}

if( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
sizeof(opt)) < 0 )
{
perror("setsockopt");
exit(EXIT_FAILURE);
}

//type of socket created
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );

//bind the socket to localhost port 8888
if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
printf("Listener on port %d \n", PORT);

if (listen(master_socket, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}


addrlen = sizeof(address);
puts("Waiting for connections ...");

for(;;)
{

//clear the socket set
FD_ZERO(&readfds);
FD_ZERO(&writefds);

//add master socket to set
FD_SET(master_socket, &readfds);
FD_SET(master_socket, &writefds);


max_sd = master_socket;

//add child sockets to set
for ( i = 0 ; i < max_clients ; i++)
{
//socket descriptor
sd = client_socket[i];

//if valid socket descriptor then add to read list
if(sd > 0)
FD_SET( sd , &readfds);

//highest file descriptor number, need it for the select function
if(sd > max_sd)
max_sd = sd;
}

//wait for an activity on one of the sockets , timeout is NULL ,
//so wait indefinitely
activity = select( max_sd + 1 , &readfds , &writefds, NULL , NULL);

if ((activity < 0) && (errno!=EINTR))
{
printf("select error");
}


if (FD_ISSET(master_socket, &readfds))
{
if ((new_socket = accept(master_socket,
(struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}

else {

printf("Connected to socket \n");

}
bzero(buffer, 1025);

int n=0;

read(new_socket, buffer, sizeof(buffer));

printf("From client: %s\t To client: ", buffer);

bzero(buffer, 1025);

//add new socket to array of sockets
for (i = 0; i < max_clients; i++)
{
//if position is empty
if( client_socket[i] == 0 )
{
client_socket[i] = new_socket;
printf("Adding to list of sockets as %d\n" , i+1);
}
}
}

else if(FD_ISSET(master_socket, &readfds)) {

printf("From client: %s\t To client : ", buffer);
bzero(buffer, 1025);

// copy server message in the buffer
while ((buffer[n++] = getchar()) != '\n')
;

write(new_socket, buffer, sizeof(buffer));

}


else{
//else its some IO operation on some other socket
for (i = 0; i < max_clients; i++)
{
sd = client_socket[i];

if (FD_ISSET( sd , &readfds))
{
//Check if it was for closing , and also read the
//incoming message
if ((valread = read( sd , buffer, 1024)) == 0)
{

close( sd );
client_socket[i] = 0;
}

//Echo back the message that came in
else
{


}
}
}
}//else

}

return 0;
}

这是客户端的代码

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>

#define MAX 1000
#define PORT 8080
#define SA struct sockaddr

void func(int sockfd)
{
char buff[MAX];
int n;
int firstConnect = 1;

for (;;)
{

bzero(buff, sizeof(buff));
n = 0;

if(firstConnect==1) {
printf("Enter the string : ");
firstConnect = 0;

while ((buff[n++] = getchar()) != '\n')
;
write(sockfd, buff, sizeof(buff));

}


bzero(buff, sizeof(buff));

read(sockfd, buff, sizeof(buff));

printf("From Server: %s\t To Server : ", buff);


while ((buff[n++] = getchar()) != '\n');
write(sockfd, buff, sizeof(buff));

if ((strncmp(buff, "exit", 4)) == 0)
{
printf("Client Exit...\n");
break;
}
}
}


int main()
{

printf("CLIENT");
int sockfd, connfd;
struct sockaddr_in servaddr, cli;

// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");

bzero(&servaddr, sizeof(servaddr));

// assign IP, PORT
servaddr.sin_family = AF_INET;

// servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_addr.s_addr = inet_addr("127.8.1.0");

servaddr.sin_port = htons(PORT);

// connect the client socket to server socket
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0)
{
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");

// function for chat
func(sockfd);

// close the socket
close(sockfd);
}

最佳答案

作为侧节点,您似乎希望read 以零终止接收到的数据。事实并非如此。接收数据的长度在read的返回值中,不可忽略。

您还希望 write 找到您发送的字符串的结尾。那不会发生。您必须指定要发送的数据的确切长度,而不是包含数据的缓冲区的长度。

send/writerecv/read 函数处理二进制数据而不是零终止字符串,并且可以发送/接收小于指定大小的数据或可能返回错误.了解如何通过不忽略返回值和处理错误以及部分读取和写入来正确使用这些函数。

关于c - C语言多客户端服务器通信程序如何同时使用writefds和readfds?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54211683/

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