【问题标题】:How do I return a char from a function that uses winsock to recv from socket?如何从使用winsock从套接字接收的函数中返回一个字符?
【发布时间】:2010-11-28 19:20:58
【问题描述】:

当我尝试打印缓冲区时,我的应用程序崩溃了。否则,它工作正常。 这是代码:

irc.h

  class IRC
            {
              public:
                      void sockconnect(char * hName, int portNum);
                          void sockwrite(char* sendbuf);
                          char sockread(void);
                          bool connected;
                  private:
                          WSADATA wsaData;
                          SOCKET m_socket;
                          sockaddr_in clientService;
                          LPHOSTENT hostEntry;

};

irc.cc

char IRC::sockread(void)

  {
    int result;
    char buffer[DEFAULT_BUFLEN];
        result = recv(m_socket, buffer, DEFAULT_BUFLEN, 0);

        if (result > 0) {
             return *buffer;
              }
          else if (result == 0)
              {
             connected = false;
                 return *buffer;
              }
          else {
         printf("recv failed with error: %d\n", WSAGetLastError());
         return *buffer;
        }

   }

ma​​in.cc

 IRC client;

 while (client.connected == true) {
     char buffer = client.sockread();
         if (buffer == NULL)
           break;


        printf ("Buffer: %s\n",buffer);
       }

【问题讨论】:

    标签: c++ visual-studio-2010 visual-c++ windows-xp winsock2


    【解决方案1】:

    如果要打印第一个字符,请使用

    printf ("Buffer: %c\n",buffer);
    

    如果你想打印整个,那么 sockread 应该返回整个缓冲区,而不是第一个字符。为此,您需要返回缓冲区第一个元素的地址,在这种情况下,该地址应该已经动态分配。

    printf ("Buffer: %s\n",buffer);
    

    编辑经过思考,我认为您想要后者以通过以下方式更改 sockread() 函数:

    • 将返回类型从char 更改为char* 或更好的const char*
    • char buffer[DEFAULT_BUFLEN];char* buffer = new char[DEFAULT_BUFLEN];
    • return *bufferreturn buffer

    另外,在这种情况下不要忘记删除缓冲区

    const char* buffer = client.sockread(); //not char buffer as in your code
    printf ("Buffer: %s\n",buffer);
    delete [] buffer;
    

    【讨论】:

    • 对不起,我不明白。这不是我已经在做的吗?
    • @thorvald:不,实际上您只返回第一个字符。查看我的编辑
    • 您正在返回一个字符(缓冲区中的第一个字符),并且您正在尝试将该字符打印为字符串(以 nul 结尾的字符 *)
    • 错误 C2440: 'return' : 无法从 'char *' 转换为 'char'
    • @thorvald:是的,你应该更改 sockread 以返回 char* 而不是 char
    【解决方案2】:

    你需要使用 std::string。你不能返回那个缓冲区——它在本地堆栈上。即使您成功地返回了一个指向它的实际指针,而不仅仅是一个字符,这就是您所做的,那么它也会超出范围并且其中的数据无效。

    std::string 解决了所有这些问题。你只需使用它,它就完成了。您还有其他问题,例如实际上失败时返回的缓冲区无效。这就是例外。

    std::string IRC::sockread()
    {
        std::string s;
        s.resize(DEFAULT_BUFLEN);
        int result = recv(m_socket, &s[0], DEFAULT_BUFLEN, 0);
    
        if (result > 0) {
            return s;
        } else if (result == 0) {
            connected = false;
        } else {
            std::cout << "recv failed with error " << WSAGetLastError() << "\n";
        }
        throw std::runtime_error("Socket connection failed!");
    }
    

    【讨论】:

    • 我试过这个例子,但是当我从主函数调用它时它没有打印任何东西。 std::string s; s.resize(512); s = client.sockread(); printf("%s\n",s);但它每次都打印“Ìü”。另一个答案中的示例有效。
    • @thorvald:那是因为你应该使用 std::cout,正如我所展示的,而不是 printf。此外,您不必在函数之外调整字符串的大小。你可以做std::cout &lt;&lt; client.sockread();std::string s = client.sockread();
    • 如果我使用 std::cout,它不会编译。错误 C2679:二进制“
    • @thorvald:别忘了#include &lt;string&gt;
    • 哦,我包含的是 string.h 而不是 string。 ://
    猜你喜欢
    • 2013-07-31
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 2023-03-31
    • 1970-01-01
    • 2020-01-16
    相关资源
    最近更新 更多