Basit bir sunucuya ve istemci C koduna sahip, çokyönlüler için bir konu sohbet odası (pthread kütüphanesi) kullanarak sohbet odası yapıyorum. Sorun şu ki, sunucunun bir istemcinin soket üzerinden diğer tüm istemcilere gönderdiği her mesajı yazmasını sağlamanın bir yolu düşünemem. Burada başka benzer yazılar okudum ve çaresizdi. Lütfen bana okul için bunu yapmam için bana yardım edin. Her iki kodu da hemen göndereceğim.Linux'ta C/Soket programlamasındaki sohbet odası
Server.c:
#include<stdio.h>
#include<string.h> //strlen
#include<stdlib.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h> //write
#include<pthread.h> //for threading , link with lpthread
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int socket_desc , new_socket , c , *new_sock;
struct sockaddr_in server , client;
char *message;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8888);
//Bind
if(bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("bind failed");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while((new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)))
{
puts("Connection accepted");
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = new_socket;
if(pthread_create(&sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
//Now join the thread , so that we dont terminate before the thread
//pthread_join(sniffer_thread , NULL);
puts("Handler assigned");
}
if (new_socket<0)
{
perror("accept failed");
return 1;
}
return 0;
}
/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size;
char *message , client_message[2000];
//Receive a message from client
while((read_size = recv(sock , client_message , 2000 , 0)) > 0)
{
//Send the message back to client
write(sock , client_message , strlen(client_message));
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
//Free the socket pointer
free(socket_desc);
return 0;
}
Client.c
#include<stdio.h> //printf
#include<string.h> //strlen
#include<sys/socket.h> //socket
#include<arpa/inet.h> //inet_addr
int main(int argc , char *argv[])
{
int sock;
struct sockaddr_in server;
char message[1000] , server_reply[2000];
//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
puts("Socket created");
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(8888);
//Connect to remote server
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
return 1;
}
puts("Connected\n");
puts("Bienvenido al Chatroom, puedes empezar a escribir en la sala!");
//keep communicating with server
while(1)
{
printf("Enter message: ");
fgets(message, sizeof(message),stdin);
//scanf("%s" , message);
//Send some data
if(send(sock , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
//Receive a reply from the server
if(recv(sock , server_reply , 2000 , 0) < 0)
{
puts("recv failed");
break;
}
printf("Server Reply: %s\n", server_reply);
server_reply[0]='\0';
}
close(sock);
return 0;
}
Bu programlar çok basit, istemci kullanıcı konsolda yazıyor ve sunucu tekrar aynı mesajı göndermek neyi gönderir. Aynı mesajı sadece her mesaja (istemci) bağlı olarak göndermek için sunucuya ihtiyacım var (sadece orijinal mesajı gönderen değil).
Herkes bakım için bu uzun olduğunu biliyorum ama eğer yapabilirsen, ben bir muteks ile korunan tüm istemciler küresel bir tablo, gerek biraz yardım :)
Bunun için iş parçacığı kullanmanız gerekli mi? Daha kolay bir tasarım, tek iş parçacıklı olabilir ve select() veya poll() kullanarak G/Ç işlemlerini çoğaltır. Sonra tüm istemcilerin soketlerine yazmak basit bir for döngüsü kullanarak yapılabilir. –
Oh teşekkürler, muhtemelen daha kolay olacaktır. Yine de select() veya poll() haha'yı nasıl kullanacağımı bilmiyorum. İplik kullandım çünkü son zamanlarda onları nasıl kullanacağımı öğrendim ve problemim için oldukça etkili bir çözüm gibi görünüyorlar haha. Bu fonksiyonlardan herhangi birinin nasıl kullanıldığına dair bana biraz bilgi verebilir misin? :) –
Dişler güçlü bir ilaçtır - çok dikkatli olmadıkça sizi ısıtabilirler. Görevini gerçekleştirmenin başka bir yolu olmadıkça bunları kullanmamayı denerim. Select() için şu bağlantılara bakın: http://www.lowtek.com/sockets/select.html http://www.binarytides.com/multiple-socket-connections-fdset-select-linux/ –