1

我设置了两个通过 unix 域套接字共享数据的简单程序。一个程序从队列中读取数据并将其发送到另一个应用程序。在发送之前,每条数据都在前面附加四个字节的长度,如果小于四个字节,则剩余的字节是'^'符号。

客户端应用程序然后读取前四个字节,将缓冲区设置为适当的大小,然后读取其余部分。我遇到的问题是第一次通过消息将被完美发送。此后每隔一段时间都会发送额外的数据,因此会出现“多么美好的一天”之类的消息,例如“多么美好的一天??X??”。所以我觉得缓冲区没有被正确清除,但我似乎找不到它。

客户端代码:

listen(sock, 5);
for (;;) 
{
    msgsock = accept(sock, 0, 0);
    if (msgsock == -1)
        perror("accept");
    else do 
    {
        char buf[4];
        bzero(buf, sizeof(buf));
        if ((rval = read(msgsock, buf, 4)) < 0)
        perror("reading stream message");

        printf("--!%s\n", buf);

        string temp = buf;
        int pos = temp.find("^");
        if(pos != string::npos)
        {
            temp = temp.substr(0, pos);
        }

        int sizeOfString = atoi(temp.c_str());
        cout << "TEMP STRING: " << temp << endl;
        cout << "LENGTH " << sizeOfString << endl;
        char feedWord[sizeOfString];
        bzero(feedWord, sizeof(feedWord));

        if ((rval = read(msgsock, feedWord, sizeOfString)) < 0)
              perror("reading stream message");

          else if (rval == 0)
              printf("Ending connection\n");
          else
              printf("-->%s\n", feedWord);
              bzero(feedWord, sizeof(feedWord));
              sizeOfString = 0;
              temp.clear();
      } 
        while (rval > 0);
      close(msgsock);
  }
  close(sock);
  unlink(NAME);

服务器代码

                pthread_mutex_lock(&mylock);
                string s;
                s.clear();
                s = dataQueue.front();
                dataQueue.pop();
                pthread_mutex_unlock(&mylock);

                int sizeOfString = strlen(s.c_str());
                char sizeofStringBuffer[10];

                sprintf(sizeofStringBuffer, "%i", sizeOfString);
                string actualString = sizeofStringBuffer;
                int tempSize = strlen(sizeofStringBuffer);

                int remainder = 4 - tempSize;
                int x;
                for(x =0; x < remainder; x++)
                {
                    actualString = actualString + "^";
                }

                cout << "LENGTH OF ACTUAL STRING: " << sizeOfString << endl;

                actualString = actualString + s;

                cout << "************************" << actualString << endl;
                int length = strlen(actualString.c_str());

                char finalString[length];
                bzero(finalString, sizeof(finalString));
                strcpy(finalString, actualString.c_str());

                           if (write(sock, finalString, length) < 0)
                           perror("writing on stream socket");      
4

3 回答 3

2

而不是用' ^'填充你的数据包长度,你最好这样做:

snprintf(sizeofStringBuffer, 5, "%04d", sizeOfString);

使值填充为 0 - 那么您不需要解析接收器代码中的 '^' 字符。

还请编辑您的调试代码 - 当前代码中只有一个write(),它与您对协议的描述不匹配。

理想情况下 - 将您的发送例程拆分为自己的功能。您还可以利用writev()处理将保存“长度”字段的字符串与保存实际数据的缓冲区合并,然后将它们作为单个 atomic 发送write()

未经测试的代码如下:

int write_message(int s, std::string msg)
{
     struct iovec iov[2];
     char hdr[5];

     char *cmsg = msg.c_str();
     int len = msg.length();

     snprintf(hdr, 5, "%04d", len);  // nb: assumes len <= 9999;

     iov[0].iov_base = hdr;
     iov[0].iov_len = 4;

     iov[1].iov_base = cmsg;
     iov[1].iov_len = len;

     return writev(s, iov, 2);
}
于 2009-05-21T18:11:31.013 回答
2

您必须检查两者的返回值,write不仅read-1对于简短的(少于请求的)写入/读取。您似乎也只是在打印错误后继续perror- do an exit(2)or something there。

于 2009-05-21T18:12:21.700 回答
0

两件事情:

首先 - 在服务器端,您正在注销阵列的末尾。

char finalString[length];
bzero(finalString, sizeof(finalString));
strcpy(finalString, actualString.c_str());

将字符strcpy()复制length+1finalString(字符拉空终止符)。

其次(并且最有可能是问题所在)-在客户端,您不是 null 终止您读入的字符串,因此printf()将打印您的字符串,然后在堆栈上的任何内容直到它达到 null 为止。

将两个缓冲区都增加一,您应该会处于更好的状态。

于 2009-05-22T20:17:05.157 回答