在 C 中管理具有 2 个客户端的服务器中的多个线程
Manage multiple Threads in a Server with 2 Clients , in C
我必须创建一个允许来自 2 个不同客户端的连接的服务器。所以我使用了线程。客户端和服务器通信良好,但线程有问题。基本上对于第一个客户端(select 咖啡类型的用户)我想将咖啡的价格发送到服务器。然后我想把这个价格从服务器发送到另一个客户端(然后我必须插入硬币和其他我必须实现的东西)。
当我运行服务器和第一个客户端服务器returns我的价格所以没问题。但是,当我尝试连接其他客户端时,程序出现 returns 错误。忽略第一部分,看看哪里有线程。我知道这里有错误,但是我找不到。
当我运行第一个客户:
iMac:bin $ ./client1 localhost
在服务器上我有这个:
Price received from client1: 0.500000 €
相反,当我 运行 第二个客户时:
iMac:bin $ ./client2 localhost
Price received from server = 0
在服务器上我有这个:
read() failed: Undefined error: 0
从服务器收到的价格应该是 = 0.500000€ 但我出错了。服务器在 prodSelected() 中再次输入,但我希望当我 运行 client2 服务器仅在 insertCoin() 中输入时。我希望服务器在调用 client1 时仅在 prodSelected() 中输入。所以在 CLIENT1 中我想 select 咖啡,CLIENT1 将咖啡的价格发送到服务器,然后服务器将咖啡的价格发送到 CLIENT2。
非常感谢您的宝贵时间。请原谅我的英语。
这是服务器:
#include"funzioni.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>
void *prodSelected(void *);
void *insertCoin(void *);
float price= 0; //GLOBAL VARIABLE WHERE PRICE IS STORED
int main(int argc , char *argv[])
{
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Il socket non può essere creato");
}
puts("Socket creato");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 3490 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind() fallito. Errore");
return 1;
}
puts("bind() avvenuto con successo");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Attendendo connessioni in entrata...");
c = sizeof(struct sockaddr_in);
//Accept and incoming connection
puts("Attendendo connessioni in entrata...");
c = sizeof(struct sockaddr_in);
pthread_t product;
pthread_t coin;
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accettata");
if( pthread_create( &product, NULL , &prodSelected, (void*) &client_sock) != 0){
perror("Il thread non può essere creato");
return 1;
}
if( pthread_create( &coin , NULL , &insertCoin, (void*) &client_sock) != 0){
perror("Il thread non può essere creato");
return 1;
}
if(pthread_join( coin , NULL)!=0){
fprintf(stderr, "pthread_join() Errore");
exit(0);
}
if(pthread_join( product , NULL)!=0){
fprintf(stderr, "pthread_join() Errore");
exit(0);
}
puts("Handler assegnato");
}
if (client_sock < 0){
perror("accept() fallito");
return 1;
}
return 0;
}
pthread_mutex_t client1=PTHREAD_MUTEX_INITIALIZER;
/*
* Handle client connection
* */
//Receive price of the product from Client1
void *prodSelected(void *socket_desc){
int sock = *(int*)socket_desc;
int received_int = 0;
int return_status;
pthread_mutex_lock(&client1);
return_status = read(sock, &received_int, sizeof(received_int)); //
if (return_status > 0) {
fprintf(stdout, "Product selected = %d\n", ntohl(received_int));
}
else {
perror("read() failed ");
exit(1);
}
//these are some function included in my header file
stampaPrezzo(ntohl(received_int));
prezzo = comunicaPrezzo(ntohl(received_int));
pthread_mutex_unlock(&client1);
printf("Price received from client1: %f €\n",price );
return 0;
}
// Send price from Server to Client2.
void *insertCoin(void *arg){
int sock = *(int*)arg;
int number_to_send = price;
int converted_number = htonl(number_to_send);
write(sock, &converted_number, sizeof(converted_number));
}
也许你应该详细阅读关于 accept() 的文档。
DESCRIPTION
The accept() system call is used with connection-based socket types
(SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection
request on the queue of pending connections for the listening socket,
sockfd, creates a new connected socket, and returns a new file descrip‐
tor referring to that socket. The newly created socket is not in the
listening state. The original socket sockfd is unaffected by this
call.
accept() returns 引用客户端-服务器连接的新 fd。
存储库可以解决您的问题:https://github.com/yorickdewid/Chat-Server
我必须创建一个允许来自 2 个不同客户端的连接的服务器。所以我使用了线程。客户端和服务器通信良好,但线程有问题。基本上对于第一个客户端(select 咖啡类型的用户)我想将咖啡的价格发送到服务器。然后我想把这个价格从服务器发送到另一个客户端(然后我必须插入硬币和其他我必须实现的东西)。
当我运行服务器和第一个客户端服务器returns我的价格所以没问题。但是,当我尝试连接其他客户端时,程序出现 returns 错误。忽略第一部分,看看哪里有线程。我知道这里有错误,但是我找不到。
当我运行第一个客户:
iMac:bin $ ./client1 localhost
在服务器上我有这个:
Price received from client1: 0.500000 €
相反,当我 运行 第二个客户时:
iMac:bin $ ./client2 localhost
Price received from server = 0
在服务器上我有这个:
read() failed: Undefined error: 0
从服务器收到的价格应该是 = 0.500000€ 但我出错了。服务器在 prodSelected() 中再次输入,但我希望当我 运行 client2 服务器仅在 insertCoin() 中输入时。我希望服务器在调用 client1 时仅在 prodSelected() 中输入。所以在 CLIENT1 中我想 select 咖啡,CLIENT1 将咖啡的价格发送到服务器,然后服务器将咖啡的价格发送到 CLIENT2。
非常感谢您的宝贵时间。请原谅我的英语。
这是服务器:
#include"funzioni.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>
void *prodSelected(void *);
void *insertCoin(void *);
float price= 0; //GLOBAL VARIABLE WHERE PRICE IS STORED
int main(int argc , char *argv[])
{
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Il socket non può essere creato");
}
puts("Socket creato");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 3490 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind() fallito. Errore");
return 1;
}
puts("bind() avvenuto con successo");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Attendendo connessioni in entrata...");
c = sizeof(struct sockaddr_in);
//Accept and incoming connection
puts("Attendendo connessioni in entrata...");
c = sizeof(struct sockaddr_in);
pthread_t product;
pthread_t coin;
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accettata");
if( pthread_create( &product, NULL , &prodSelected, (void*) &client_sock) != 0){
perror("Il thread non può essere creato");
return 1;
}
if( pthread_create( &coin , NULL , &insertCoin, (void*) &client_sock) != 0){
perror("Il thread non può essere creato");
return 1;
}
if(pthread_join( coin , NULL)!=0){
fprintf(stderr, "pthread_join() Errore");
exit(0);
}
if(pthread_join( product , NULL)!=0){
fprintf(stderr, "pthread_join() Errore");
exit(0);
}
puts("Handler assegnato");
}
if (client_sock < 0){
perror("accept() fallito");
return 1;
}
return 0;
}
pthread_mutex_t client1=PTHREAD_MUTEX_INITIALIZER;
/*
* Handle client connection
* */
//Receive price of the product from Client1
void *prodSelected(void *socket_desc){
int sock = *(int*)socket_desc;
int received_int = 0;
int return_status;
pthread_mutex_lock(&client1);
return_status = read(sock, &received_int, sizeof(received_int)); //
if (return_status > 0) {
fprintf(stdout, "Product selected = %d\n", ntohl(received_int));
}
else {
perror("read() failed ");
exit(1);
}
//these are some function included in my header file
stampaPrezzo(ntohl(received_int));
prezzo = comunicaPrezzo(ntohl(received_int));
pthread_mutex_unlock(&client1);
printf("Price received from client1: %f €\n",price );
return 0;
}
// Send price from Server to Client2.
void *insertCoin(void *arg){
int sock = *(int*)arg;
int number_to_send = price;
int converted_number = htonl(number_to_send);
write(sock, &converted_number, sizeof(converted_number));
}
也许你应该详细阅读关于 accept() 的文档。
DESCRIPTION
The accept() system call is used with connection-based socket types
(SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection
request on the queue of pending connections for the listening socket,
sockfd, creates a new connected socket, and returns a new file descrip‐
tor referring to that socket. The newly created socket is not in the
listening state. The original socket sockfd is unaffected by this
call.
accept() returns 引用客户端-服务器连接的新 fd。
存储库可以解决您的问题:https://github.com/yorickdewid/Chat-Server