Send messages between sockets

I have 1 server that's built with C++ and c sockets in Unix. The client is using QT and the socket api that comes with it.

The server sends 345 bytes of data to the client.

Sending message from server:

void Moderator::testSynch(){
  int type = (int) SYNCRHONIZE_M;
  //Update all connected clients with info about other clients
  for(int i = 0; i<nrOfClients_; i++){
    const TcpSocket &clientSocket = clients_[i].getSocket();
    int clientID = clients_[i].getID();

    int tempType = htonl(type);
    int tempClientID = htonl(clientID);
    int tempNrOfClients = htonl(funNrOfClients);

    clientSocket.writeData((const char*) &tempType, sizeof(tempType));
    clientSocket.writeData((const char*) &tempClientID, sizeof(tempClientID));
    clientSocket.writeData((const char*) &tempNrOfClients, sizeof(tempNrOfClients));

    for(int j = 0; j<nrOfClients; j++){ //Send info about connectecd clients

        int tempLength = (int) clients_[j].getName().length();
        int tempID = clients_[j].getID();
        string tempName = clients_[j].getName();

        tempID = htonl(tempID);
        tempLength = htonl(tempLength);
        clientSocket.writeData((const char*) &tempID, sizeof(tempID));
        clientSocket.writeData((const char*) &tempLength, sizeof(tempLength));
        clientSocket.writeData(tempName.c_str(), (int)tempName.length());

    }
  }
}

bool TcpSocket::writeData(const char* buffer, int length)const{
  size_t bytesLeft = length;
  ssize_t bytesWritten = 0;

  while((bytesWritten = write(socketFD_, buffer, bytesLeft)) > 0){
    bytesLeft -= bytesWritten;
    buffer += bytesWritten;
  }
  return bytesLeft == 0;
}

Reading message in client:

 void ChatClient::readMessage(Message &message){

 if(socket_->readData((char*) &type, sizeof(type))){
   if(type == SYNCRHONIZE_M){
        int nrOfUsers = 0;

        socket_->readData((char*) &ID_, sizeof(ID_)); //Set the client ID that server gave us
        socket_->readData((char*) &nrOfUsers, sizeof(nrOfUsers));

        ID_ = ntohl(ID_);
        nrOfUsers = ntohl(nrOfUsers);
        qDebug("%s=%d", "nrOfUsers", nrOfUsers);
        message.setMessageType(SYNCRHONIZE_M);
        messageOK = true;
        for(int i = 0; i<nrOfUsers; i++){ //Update client with all connected users to server
            int userID = 0;
            int nameLength = 0;

            socket_->readData((char*) &userID, sizeof(userID));
            socket_->readData((char*) &nameLength, sizeof(nameLength));

            userID = ntohl(userID);
            nameLength = ntohl(nameLength);

            if(nameLength > 0){
                qDebug("%s=%d", "nameLength", nameLength);
                buffer = new char[nameLength];
                socket_->readData(buffer, nameLength);

                message.addUser(ConnectedUser(buffer, nameLength, userID));
                delete [] buffer;
            }
        }
    }
}
}

bool TcpSocket::readData(char* buffer, int length){
    int bytesLeft = length;
    int bytesRead = 0;

    while((bytesRead = qSocket_->read(buffer, bytesLeft)) > 0){
       bytesLeft -= bytesRead;
       buffer += bytesRead;

    }
    return bytesLeft == 0;
}

The problem i'm having is sometimes the entire message from server is not available at once.

For example, first 45 bytes is available in the client. The client then tries to read the entire message (345 bytes) which results in weird behavior. Immediately after the client is done reading the next 300 bytes becomes available.

What is the best way to send messages between sockets? Also, how can I determine if the entire message have been received?

Answers


You have some notion of a "message" that exists only in your head. Nothing in your code reflects that. If you have an application protocol that involves a "message" that is sent, then you need to write code to send a message and code to receive a message based on your protocol's definition of a message. TCP only provides streams of bytes and doesn't glue them together for the application into anything bigger than one byte.


Need Your Help

Strategy for sharing resources between projects

c# .net asp.net resources satellite-assembly

I have a central library (DLL) called Core that is used by many projects (Some web apps, some win forms, some other class libraries).

Compare a string which has a param

c# regex csv string.format

I am reading in a header from a file which has time fields for example Time (UTC +1). I then need to compare this with a list of stored headers to work out if the file is valid however my stored he...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.