Reputation: 3506
I am trying to write a little tcp chatroom in c++. When I connect one client to the server, the server receives correctly and can answer/echo if wanted. When I connect a second client and send a message with him to the server the other client receives that message too. But to receive the next messages of the other clients
When I have two clients connected to the server and the first client (C1) is sending, the other client (C2) receives that message correctly too. But from that point, that client (C2) has to send something himself in order to receive another message from client (C1). And the other way around. I hope thats understandable.
I thought that it has something to do with the fact that the "getline" is blocking from continueing to receiving again, so I tried to use threads but that didnt work either. Now I am thinking that I really has something to do with the streaming "property" of TCP.
Here is the server code:
#include <iostream> #include <sys/types.h> #include <unistd.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> #include <arpa/inet.h> #include <string.h> #include <string> #include <sys/select.h> #include <fcntl.h> #include <vector> #include <thread> using namespace std; int main() { // create server-socket int listening = socket(AF_INET, SOCK_STREAM, 0); fcntl(listening, F_SETFL, O_NONBLOCK); if (listening == -1) { cerr << "Failed to create socket." << endl; return -1; } // bind socket to ip/port sockaddr_in hint; hint.sin_family = AF_INET; hint.sin_port = htons(54000); inet_pton(AF_INET, "0.0.0.0", &hint.sin_addr); // check if can bind if (bind(listening, (sockaddr*)&hint, sizeof(hint)) == -1) { cerr << "Failed to bind to IP/port" << endl; return -2; } // check if can listen if (listen(listening, SOMAXCONN) == -1) { cerr << "Failed to listen." << endl; return -3; } // fd_set master; FD_ZERO(&master); FD_SET(listening, &master); while (true) { for (int i=0; i<=FD_SETSIZE; i++) { if (FD_ISSET(i, &master)) { int sock = i; if(sock == listening) { sockaddr_in client; socklen_t clientSize = sizeof(client); char host[NI_MAXHOST]; char svc[NI_MAXSERV]; int clientSocket = accept(listening, (sockaddr*)&client, &clientSize); FD_SET(clientSocket, &master); string acceptMessage = "Successfully connected to the server."; send(clientSocket, acceptMessage.c_str(), (acceptMessage.size() + 1), 0); } else { char buffer[4096]; memset(buffer, 0, 4096); // receive from client int bytesReceived = recv(sock, buffer, 4096, MSG_DONTWAIT); if (bytesReceived == -1) { ; } else if (bytesReceived == 0) { close(sock); FD_CLR(sock, &master); cout << "Client disconnected." << endl; } else { cout << "received: " << string(buffer, 0, bytesReceived) << endl; for (int j=0; j<100; j++) { int outSock = j; if (FD_ISSET(j, &master)) { if (outSock != listening && outSock != 63) { if (outSock == sock) { string echoMsg = "<echo>" + string(buffer, 0, bytesReceived); send(outSock, echoMsg.c_str(), (echoMsg.size() + 1), 0); ; } else { send(outSock, buffer, bytesReceived, 0); } } } } } } } } } return 0; }
Here the client code:
#include <iostream> #include <sys/types.h> #include <unistd.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> #include <arpa/inet.h> #include <string.h> #include <string> #include <fcntl.h> #include <future> #include <thread> using namespace std; void *sendMessage(string userInput, int sock); void *receiveMessage(char buffer[4096], int sock); void *sendMessage(string userInput, int sock) { // input message to send cout << ">> "; getline(cin, userInput); // send message int sendResult = send(sock, userInput.c_str(), userInput.size() + 1, 0); if (sendResult == -1) { cout << "Could not send to server." << endl; } } void *receiveMessage(char buffer[4096], int sock) { int bytesReceived = recv(sock, buffer, 4096, 0); if (bytesReceived == -1) { cout << "There has been a server-issue." << endl; } else if (bytesReceived == 0) { cout << "Server closed." << endl; } else { string receivedString = string(buffer, 0, bytesReceived); string checkEcho = receivedString.substr(0, 6); if (checkEcho.compare("<echo>") == 0) { ; } else { cout << "SERVER: " << string(buffer, bytesReceived) << endl; } } } int main() { // create socket int sock = socket(AF_INET, SOCK_STREAM, 0); //fcntl(sock, F_SETFL, O_NONBLOCK); if (sock == -1) { return 1; } // port and server-ip int port = 54000; string ipAddress = "127.0.0.1"; // create buffer for messages char buffer[4096]; // ipv4 socket sockaddr_in hint; hint.sin_family = AF_INET; hint.sin_port = htons(port); inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr); // try connect to server int connectResult = connect(sock, (sockaddr*)&hint, sizeof(hint)); if (connectResult == -1) { cout << "Could not connect to server." << endl; return -1; } else { receiveMessage(buffer, sock); } string userInput; while (true) { // receive from server memset(buffer, 0, 4096); thread t1(sendMessage, userInput, sock); thread t2(receiveMessage, buffer, sock); //sendMessage(userInput, sock); //receiveMessage(buffer, sock); t1.join(); t2.join(); } // close socket close(sock); return 0; }
I have found some similiar questions but none could help me solve my problem. This bugs me for quite some time now, so I'd really appreciate some answers :)
Upvotes: 0
Views: 345