我正在尝试用 C 语言编写一个简单的 CLI 消息传递程序。我发现了套接字。我编写了一个简单的程序,客户端可以在其中写入一些消息,服务器将其打印在服务器端我尝试打开
我正在尝试用 C 语言编写一个简单的 CLI 消息传递。我发现了套接字。我编写了一个简单的程序,客户端可以写入一些消息,服务器将其打印在服务器端。我尝试打开多个客户端,但它只接受一个客户端,
我想制作一个程序,让多个客户端可以加入服务器而不是一个,并编写一些消息,目前只有服务器在服务器端打印客户端消息,但是当其他客户端加入并发送消息时,我希望客户端能够看到其他客户端消息目前我有server.c
/*
server.c
*/
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MAX 256
#define PORT 8080
int main() {
int socket_return, accept_return, bind_return, listen_return;
struct sockaddr_in server_address, peer_address;
// Creating socket
socket_return = socket(AF_INET, SOCK_STREAM, 0);
if (socket_return == -1) {
perror("socket creation failed\n");
return -1;
} else {
printf("socket created\n");
}
//empty the server address`
bzero(&server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(PORT);
// binding socket
bind_return = bind(socket_return, (struct sockaddr *)&server_address, sizeof(server_address));
if (bind_return == -1) {
perror("binding failed\n");
close(socket_return);
return -1;
} else {
printf("binding done\n");
}
// listening the socket
listen_return = listen(socket_return, 5);
if (listen_return == -1) {
perror("listening failed");
close(socket_return);
return -1;
} else {
printf("server is listening...\n");
}
socklen_t peer_address_len = sizeof(peer_address);
// accept connection
accept_return = accept(socket_return, (struct sockaddr *)&peer_address, &peer_address_len);
if (accept_return == -1) {
perror("accepting failed\n");
close(socket_return);
return -1;
} else {
printf("connection accepted\n");
}
char msg[MAX];
while (1) {
bzero(msg, sizeof(msg));
// Read message
ssize_t bytes_read = read(accept_return, msg, sizeof(msg) );
if (bytes_read == 0) {
printf("client disconnected\n");
break;
} else if (bytes_read < 0) {
perror("failed to read message\n");
break;
}
//displaying client message
printf("From client: %s", msg);
}
// closing
close(accept_return);
close(socket_return);
return 0;
}
客户端.c
/*
client.c
*/
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MAX 256
#define PORT 8080
int main() {
int socket_return, connect_return;
struct sockaddr_in server_address;
// Creating socket
socket_return = socket(AF_INET, SOCK_STREAM, 0);
if (socket_return == -1) {
printf("socket creation failed\n");
return -1;
} else {
printf("socket created\n");
}
bzero(&server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = htons(PORT);
// Connecting the server
connect_return = connect(socket_return, (struct sockaddr *)&server_address, sizeof(server_address));
if (connect_return == -1) {
printf("connection failed\n");
close(socket_return);
return -1;
} else {
printf("connected to server\n");
}
char msg[MAX];
int i;
while (1) {
bzero(msg, sizeof(msg));
printf("Enter string: ");
i = 0;
while ((msg[i++] = getchar()) != '\n');
//when server detects the client message as 'exit' close the server
if ((strncmp(msg, "exit", 4)) == 0) {
printf("Exiting client\n");
close(socket_return);
break;
}
// sending message
write(socket_return, msg, sizeof(msg));
printf("You wrote %s\n",msg);
}
// close
close(socket_return);
return 0;
}
我尝试打开多个客户端,但它只接受一个客户端
是的。您的服务器 accept()
每次运行只执行一次调用,因此它最多接受一个客户端。此外,它会全力接收和显示来自该客户端的数据,并且当该客户端断开连接或读取尝试失败时,服务器将终止。
我想制作一个程序,让多个客户端可以加入服务器而不是一个,并编写一些消息,当前只有服务器在服务器端打印客户端消息,但是当其他客户端加入并发送消息时,我希望客户端能够看到其他客户端消息
那么你需要
accept()
新客户端
解决这些问题主要有两种方式:
p5
p6
对于您的特殊情况,如果您选择使用多线程或多处理,那么您可能需要为每个客户端提供 两个 线程/进程,或者也使用多路复用,因为您希望避免从一个客户端读取/写入时的阻塞延迟从同一客户端写入/读取。
无论哪种方式,都需要进行大量的簿记管理。使用多线程/多处理时,数据结构可能稍微简单一些,但这被管理所有这些服务单元之间的同步和通信的需求所抵消。
要同时接受和处理多个客户端,您需要使用多线程的概念,例如 POSIX 线程库(pthreads)。
服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT 8080
#define BUFFER_SIZE 1024
// Function to handle client communication
void *handle_client(void *client_socket) {
int sock = *(int *)client_socket;
char buffer[BUFFER_SIZE];
int n;
while ((n = recv(sock, buffer, sizeof(buffer) - 1, 0)) > 0) {
buffer[n] = '\0'; // Null-terminate the received data
printf("Client: %s\n", buffer);
// Echo the received message back to the client
send(sock, buffer, n, 0);
}
if (n == 0) {
printf("Client disconnected\n");
} else {
perror("recv");
}
close(sock);
free(client_socket);
pthread_exit(NULL);
}
int main() {
int server_fd, new_socket, *client_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
pthread_t thread_id;
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Setting up the address structure
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
// Binding the socket
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
close(server_fd);
exit(EXIT_FAILURE);
}
// Listening for incoming connections
if (listen(server_fd, 3) < 0) {
perror("listen");
close(server_fd);
exit(EXIT_FAILURE);
}
printf("Server is listening on port %d\n", PORT);
while (1) {
// Accepting new client connection
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) {
perror("accept");
close(server_fd);
exit(EXIT_FAILURE);
}
// Allocating memory for client socket descriptor
client_socket = malloc(sizeof(int));
*client_socket = new_socket;
// Creating a new thread to handle the client
if (pthread_create(&thread_id, NULL, handle_client, (void *)client_socket) < 0) {
perror("pthread_create");
close(new_socket);
free(client_socket);
continue;
}
// Detaching the thread so that it can clean up after itself
pthread_detach(thread_id);
}
close(server_fd);
return 0;
}
客户
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sock;
struct sockaddr_in server_address;
char buffer[BUFFER_SIZE];
char *message = "Hello from client";
// Creating socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket creation error");
exit(EXIT_FAILURE);
}
// Setting up the server address structure
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", &server_address.sin_addr) <= 0) {
perror("Invalid address / Address not supported");
close(sock);
exit(EXIT_FAILURE);
}
// Connecting to the server
if (connect(sock, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) {
perror("Connection failed");
close(sock);
exit(EXIT_FAILURE);
}
// Sending a message to the server
send(sock, message, strlen(message), 0);
printf("Message sent\n");
// Receiving a response from the server
int n = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (n > 0) {
buffer[n] = '\0'; // Null-terminate the received data
printf("Server: %s\n", buffer);
} else {
perror("recv");
}
close(sock);
return 0;
}