2012-12-28 197 views
2

我有1台服务器是用Unix和C++编写的。客户端正在使用QT和随附的套接字API。在套接字之间发送消息

服务器向客户端发送345字节的数据。从服务器

发送消息:在客户端

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; 
} 

读消息:

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; 
} 

我遇到的问题是有时从服务器的整个消息不是立即可用。

例如,前45个字节在客户端可用。客户端然后尝试读取整个消息(345字节),这会导致奇怪的行为。在客户端完成读取后,立即可用下一个300字节。

在套接字之间发送消息的最佳方式是什么?另外,如何确定是否收到了整个消息?

+1

TCP不提供任何类型的消息边界,它只是一个字节流。您需要在循环中调用read(),直到获得所有期望的数据。如果你发布了'readXXX'函数的实现,那么有人可能会提供更具体的建议。 – Barmar

+0

检查更新的帖子。 – Carlj901

+0

看起来很对我。什么是“怪异行为”?假设套接字处于阻塞模式,'readString'应该等待接收整个消息。如果它处于非阻塞模式,则在调用'read()'时需要检查'EWOULDBLOCK'错误。 – Barmar

回答

0

你有一些只存在于你脑海中的“消息”的概念。你的代码没有反映出这一点。如果您有涉及发送“消息”的应用程序协议,则需要编写代码以发送消息,并根据协议的消息定义接收消息。 TCP仅提供字节流,并且不会将它们粘贴到应用程序的任何大于一个字节的内容中。

相关问题