繁体   English   中英

客户端发送的C ++数据无法正确到达服务器

[英]C++ data sent by client doesn't reach server correctly

我有2个程序:客户端和服务器。 这两个程序使用相同的功能来发送和接收数据。 我的服务器有时无法接收到客户端发送的数据(两者都在同一台计算机上运行)。 我的协议功能:

void sendString(int fd, string str) //for sending strings
{
  unsigned long sz = str.size()+1;
  int res = write(fd, &sz, sizeof(sz));
  if (res == -1)
      throw ProtocolException("SENDSTRING SEND SIZE TROUBLE");

  res = write(fd, (void *)str.c_str(), sz);
  if (res == -1)
      throw ProtocolException("SENDSTRING SEND STRING TROUBLE");
}

void sendFlag(int fd, MessageType flag)
{
  write(fd, (void *)&flag, sizeof(MessageType));
}

string receiveString(int fd)
{
  unsigned long sz = 0;
  int readVal;
  if((readVal = read(fd, &sz, sizeof(sz))) <= 0){
    cout << "Read string size trouble " << readVal << endl;
    throw ProtocolException("Read string size trouble");
  }
  char *buf = new char[sz];
  buf[sz - 1] = '\0';
  if((readVal = read(fd, buf, sz)) <= 0){
    cout << "Read chars trouble "  << readVal << endl;
  }
  string res(buf);
  delete[] buf;
  return res;
}

MessageType receiveFlag(int fd)
{
  MessageType flag;
  read(fd, &flag, sizeof(flag));
  return flag;
}

客户端第一次失败后尝试在服务器上登录时,会发生此错误。 登录功能:

客户

string receiveOKError(){
  switch(receiveFlag(sd)){
    case MessageType::OK: return receiveString(sd) + "\n";
    case MessageType::ERROR: return "ERROR: " + receiveString(sd) + "\n";
  }
}

string sendLogin(string usrname, string password)
{
  sendFlag(sd, MessageType::LOGIN);
  sendString(sd, usrname);
  sendString(sd, password);
  return receiveOKError();
}

服务器 (注意:在调用服务器端的登录功能之前,MessageType :: LOGIN已与receiveFlag匹配)

void sendError(int fd, string message)
{
  cout << message;
  sendFlag(fd, MessageType::ERROR);
  sendString(fd, message);
}

void sendConfirm(int fd, string message) 
{
  cout << message;
  sendFlag(fd, MessageType::OK);
  sendString(fd, message);
}


void executeLogin(int fd,  ClientPoll & worker){ // server function
  string username = receiveString(fd);
  string password = receiveString(fd);
  if(dbManager.isRegistered(username)){
    ClientInfo *cl = dbManager.getClient(username, password);
    if(cl != nullptr){
        //unimportant code
        sendConfirm(fd, "Successful login");
    }
    else
        sendError(fd, "Wrong password");
  }
  else
    sendError(fd, "User doesn't exist.");

}

服务器在第二次尝试登录时接收到第一个字符串时抛出了ProtocolException。 服务器使用带轮询的非阻塞套接字,客户端使用阻塞套接字。

似乎与无阻塞套接字一起使用的read()和write()函数根本不会等待读取/写入数据,即使您确定在调用它们时数据已经准备好,也可以将它们包含在其中一会儿循环解决了这个问题:

while(read(fd, &flag, sizeof(flag))==-1);

检查0值并关闭连接也很有用,因为当客户端断开连接时,这些函数将返回0。

int sz;
while((sz = read(fd, &flag, sizeof(flag))) <= 0)
  if(sz == 0){
   //close fd or throw an exception
  }

问题未解决?试试以下方法:

客户端发送的C ++数据无法正确到达服务器

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2023 STACKOOM.COM