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
- Server receives it and sends it to Client2
- Client2 receives Client1's message, writes something back and sends it to server
- Server receives Client2's message and sends it to Client1
- Client1 receives it and writes something back which is firstly received by server, etc.etc.etc.
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
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-1on error. Ifrecvis 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.