Reputation: 31
I need to write a chat program in C using sockets and I got stuck on my way.
I have three files: server, client1, client2. My initial plan: - Client1 sends the messages to server
The loop ends when either of the clients sends "exit".
My problem in a few words:
The first exchange is successful (Client1 -> Client2, then Client2 to Client1)
However, after Client2 has sent its first message to Client1, he doesn't wait for Client1's response. He writes "Client1 : " with an empty line for the message and then immediately opens his own "Client2 : " message field.
What in God's name can be wrong here?
Client1.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int compare_strings(char a[], char b[])
{
int c = 0;
while (a[c] == b[c])
{
if (a[c] == '\0' || b[c] == '\0')
break;
c++;
}
if (a[c] == '\0' && b[c] == '\0')
return 0;
else
return -1;
}
int main() {
int clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
int cmdEXIT = 0;
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
while (cmdEXIT == 0)
{
printf("Client 1 : ");
scanf(" %[^\n]s", buffer);
send(clientSocket,buffer,sizeof buffer - 1,0);
if (compare_strings(buffer, "exit")==-1)
{
memset(&buffer[0], 0, sizeof(buffer));
recv(clientSocket, buffer, sizeof buffer - 1, 0);
if (compare_strings(buffer, "exit")==-1)
{
printf("Client 2 : ");
printf("%s\n", buffer);
memset(&buffer[0], 0, sizeof(buffer));
}
else cmdEXIT=1;
}
else cmdEXIT=1;
}
return 0;
}
Server.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int compare_strings(char a[], char b[])
{
int c = 0;
while (a[c] == b[c])
{
if (a[c] == '\0' || b[c] == '\0')
break;
c++;
}
if (a[c] == '\0' && b[c] == '\0')
return 0;
else
return -1;
}
int main() {
int welcomeSocket, newSocket, Client2;
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
char buffer[1024];
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = inet_addr("127.0.01");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
if (listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error\n");
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
Client2 = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
int cmdEXIT = 0;
while (cmdEXIT == 0)
{
recv(newSocket, buffer, 1024, 0);
printf ("%s\nEnvoie au Client2\n", buffer);
send(Client2,buffer,1024,0);
if (compare_strings(buffer, "exit")==0)
{
cmdEXIT = 1;
}
else
{
memset(&buffer[0], 0, sizeof(buffer));
recv(Client2, buffer, 1024, 0);
printf ("%s\nEnvoie au Client1\n", buffer);
send(newSocket,buffer,1024,0);
if (compare_strings(buffer, "exit")==0)
{
cmdEXIT = 1;
}
}
}
return 0;
}
Client2.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int compare_strings(char a[], char b[])
{
int c = 0;
while (a[c] == b[c])
{
if (a[c] == '\0' || b[c] == '\0')
break;
c++;
}
if (a[c] == '\0' && b[c] == '\0')
return 0;
else
return -1;
}
int main() {
int clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
int cmdEXIT = 0;
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
while (cmdEXIT == 0)
{
recv(clientSocket, buffer, sizeof buffer - 1, 0);
if (compare_strings(buffer, "exit")==-1)
{
printf("Client 1 : ");
printf("%s\n", buffer);
memset(&buffer[0], 0, sizeof(buffer));
printf("Client 2 : ");
scanf(" %[^\n]s", buffer);
send(clientSocket,buffer,sizeof buffer - 1,0);
if (compare_strings(buffer, "exit")==-1)
{
memset(&buffer[0], 0, sizeof(buffer));
}
else cmdEXIT = 1;
}
else cmdEXIT = 1;
}
return 0;
}
Result in a screenshot:
Client 2 being too bossy and not waiting for his turn to speak
Upvotes: 1
Views: 4826
Reputation: 31
So, as promised in the previous comment, here is my solution. To cut long story short: every time I test what the value of recv is. If it is equal to 1, it means that there is no message received, "the line is free" and the client can type his own message. Otherwise, he has to display the received message and only after that he can send his own text.
Client1.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
//fonction pour comparer deux strings : renvoie 0 si les valeurs sont égales
//et -1 sinon
int compare_strings(char a[], char b[])
{
int c = 0;
while (a[c] == b[c])
{
if (a[c] == '\0' || b[c] == '\0')
break;
c++;
}
if (a[c] == '\0' && b[c] == '\0')
return 0;
else
return -1;
}
int main() {
//déclaration des variables
int clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
int cmdEXIT = 0;
//paramètrage du socket
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
addr_size = sizeof serverAddr;
//connection au serveur
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
//premier message du Client1
printf("Client 1 : ");
scanf(" %[^\n]s", buffer);
send(clientSocket,buffer,sizeof buffer - 1,0);
//continuer à envoyer et recevoir des messages
//tant qu'un des clients n'envoive pas "exit"
while (cmdEXIT == 0)
{
//si le message envoyé n'est pas "exit"
if (compare_strings(buffer, "exit")==-1)
{
//vider le buffer
memset(&buffer[0], 0, sizeof(buffer));
//la valeur de recv qui est égale a 1 si recv n'a pas
//encore reçu de message
//sinon, elle est égale au nombre de bits reçu
int recvValue = recv(clientSocket, buffer, sizeof buffer - 1, 0);
//si recv n'est pas égal a 1 => un message a été reçu
if (recvValue != 1)
{
//si le contenu n'est pas "exit"
if (compare_strings(buffer, "exit")==-1)
{
//afficher le message du Client2
printf("Client 2 : ");
printf("%s\n", buffer);
//vider le buffer
memset(&buffer[0], 0, sizeof(buffer));
}
//si Client2 a envoyé "exit"
else cmdEXIT=1;
}
//si rcv est égal a 1 => pas de message reçu
else
{
//Client1 peut saisir son message
printf("Client 1 : ");
scanf(" %[^\n]s", buffer);
//et l'envoyer à Client2
send(clientSocket,buffer,sizeof buffer - 1,0);
}
}
//sinon finir la boucle
else cmdEXIT=1;
}
return 0;
}
Server.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
//fonction pour comparer deux strings : renvoie 0 si les valeurs sont égales
//et -1 sinon
int compare_strings(char a[], char b[])
{
int c = 0;
while (a[c] == b[c])
{
if (a[c] == '\0' || b[c] == '\0')
break;
c++;
}
if (a[c] == '\0' && b[c] == '\0')
return 0;
else
return -1;
}
int main() {
//déclaration des variables : Serveur et deux Clients
int welcomeSocket, Client1, Client2;
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
char buffer[1024];
//paramètrage du Serveur
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = inet_addr("127.0.01");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
//Serveur à l'écoute
if (listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error\n");
//lier le serveur et les deux clients
addr_size = sizeof serverStorage;
Client1 = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
Client2 = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
int cmdEXIT = 0;
//continuer à recevoir et envoyer des messages
//tant qu'un des clients n'envoive pas "exit"
while (cmdEXIT == 0)
{
//recevoir le message de Client1
recv(Client1, buffer, 1024, 0);
//le renvoyer a Client2
printf ("%s\nEnvoie au Client2\n", buffer);
send(Client2,buffer,1024,0);
//sortir de la boucle si Client1 a envoyé "exit"
if (compare_strings(buffer, "exit")==0)
{
cmdEXIT = 1;
}
//sinon
else
{
//vider le buffer
memset(&buffer[0], 0, sizeof(buffer));
//recevoir le message de Client2
recv(Client2, buffer, 1024, 0);
//le renvoyer a Client1
printf ("%s\nEnvoie au Client1\n", buffer);
send(Client1,buffer,1024,0);
//si Client2 a envoyé "exit"
if (compare_strings(buffer, "exit")==0)
{
cmdEXIT = 1;
}
}
}
return 0;
}
Client2.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
//fonction pour comparer deux strings : renvoie 0 si les valeurs sont egales et -1 sinon
int compare_strings(char a[], char b[])
{
int c = 0;
while (a[c] == b[c])
{
if (a[c] == '\0' || b[c] == '\0')
break;
c++;
}
if (a[c] == '\0' && b[c] == '\0')
return 0;
else
return -1;
}
int main() {
//déclaration des variables
int clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
int cmdEXIT = 0;
//paramètrage du socket
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
addr_size = sizeof serverAddr;
//connection au serveur
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
//continuer à envoyer et recevoir des messages
//tant qu'un des clients n'envoive pas "exit"
while (cmdEXIT == 0)
{
//la valeur de recv qui est égale a 1 si recv n'a pas
//encore reçu de message
//sinon, elle est egale au nombre de bits reçu
int recvValue = recv(clientSocket, buffer, sizeof buffer - 1, 0);
//si recv n'est pas égal a 1 => un message a été reçu
if (recvValue != 1)
{
//si le contenu n'est pas "exit"
if (compare_strings(buffer, "exit")==-1)
{
//afficher le message du Client1
printf("Client 1 : ");
printf("%s\n", buffer);
memset(&buffer[0], 0, sizeof(buffer));
}
//sinon sortir de la boucle
else cmdEXIT = 1;
}
else
{
//Client2 peut saisir son message
printf("Client 2 : ");
scanf(" %[^\n]s", buffer);
//Client2 envoie son message au serveur
send(clientSocket,buffer,sizeof buffer - 1,0);
//si le contenu n'est pas "exit"
if (compare_strings(buffer, "exit")==-1)
{
//vider le buffer
memset(&buffer[0], 0, sizeof(buffer));
}
//sinon sortir de la boucle
else cmdEXIT = 1;
}
}
return 0;
}
Upvotes: 2
Reputation: 71
Disclaimer: I haven't run your code myself, so the below analysis could be wrong.
I recommend you check the return value of recv
, which would return -1
on error. If recv
is encountering an error in this line of Client2.c: recv(clientSocket, buffer, sizeof buffer - 1, 0);
at the beginning of the while loop the buffer would remain zeroed out.
Thus, Client 2 would not wait for Client 1's message, and would simply print an empty string for the message from Client 1.
Let me know if any of this helps or you need more assistance. If the above is true, you should make sure that the connection is not getting interrupted, among other things.
Upvotes: 1