如何使用 winsock 的 send() 函数发送宽字符?

Posted

技术标签:

【中文标题】如何使用 winsock 的 send() 函数发送宽字符?【英文标题】:How do I send wide characters using winsock's send() function? 【发布时间】:2010-12-03 22:04:45 【问题描述】:

它说here 发送函数需要 const char*。

如何发送宽字符?我尝试了以下方法:

void MyClass::socksend(const wchar_t* wbuffer) 
   int i;
   char *buffer = (char *)malloc( MB_CUR_MAX );
   wctomb_s(&i,buffer, MB_CUR_MAX, (wchar_t)wbuffer);
   int buflen = strlen(buffer) + 2;
   char sendbuf[DEFAULT_BUFLEN];
   strcpy_s(sendbuf,buflen,buffer);
   sendbuf[buflen - 1] = '\n';
   int senderror = send(this->m_socket, sendbuf, buflen, 0);
   // error handling, etc goes here...


这并没有达到我的预期。它似乎没有向套接字发送任何内容。我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

请注意,我不确定通过套接字传输宽字符字符串的正确方法,因此对于这一部分,您只能靠自己了。我确实知道它被描述为非常多毛且令人费解。 :) 考虑到这一点,如果套接字的另一端需要一个 wchar_t 字符串,您可以使用wcslen 来获取 wbuffer 指向的字符串的长度,从而为您提供

int senderror = send( this->m_socket, (char *)wbuffer, wcslen( wbuffer ) * sizeof( wchar_t ), 0 );

您的代码中还存在一些可能的错误。 如果需要将 wchar_t 字符串转换为多字节,则应使用 wcstombs_s 而不是 wctomb_s。 wctombs_s 一次转换一个字符,而 wcstombs_s 转换一个字符串。

如果生成的字符串比 DEFAULT_BUFLEN 长,您最终将使用 '\n' 破坏字符串并删除长度超过 DEFAULT_BUFLEN 的任何数据。

send 并不总是发送整个缓冲区。您需要循环调用发送,直到所有字节都发送完毕,或者您达到某个时间限制或重试或耐心等待。

有关更多指导,请参阅here。

【讨论】:

【参考方案2】:

首先什么是宽字符?它是一个大于 8 位的整数值;这意味着您将不得不处理字节顺序。您需要将宽字符数组编码为 char 数组,然后将其作为 char 数组发送。在接收端,需要将char数组解码为宽字符数组。

函数 wctomb_s 只将单个宽字符编码为字符数组。您希望将宽字符数组编码为字符数组的函数是wcstombs_s。相应地,解码使用mbstowcs_s。

省略了错误处理(未经测试):

void MyClass::socksend(const wchar_t* wbuffer)  
   // determine the required buffer size
   size_t buffer_size;
   wcstombs_s(&buffer_size, NULL, 0, wbuffer, _TRUNCATE);

   // do the actual conversion
   char *buffer = (char*) malloc(buffer_size);
   wcstombs_s(&buffer_size, buffer, buffer_size, wbuffer, _TRUNCATE);

   // send the data
   size_t buffer_sent = 0;
   while (buffer_sent < buffer_size) 
       int sent_size = send(this->m_socket, buffer+buffer_sent, buffer_size-buffer_sent, 0);
       buffer_sent += sent_size;
   

   // cleanup
   free(buffer);

【讨论】:

以上是关于如何使用 winsock 的 send() 函数发送宽字符?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Winsock 的 send()/recv() 时是不是需要确认响应?

如何在winsock中使“发送”非阻塞

Select模型

VB6:如何获取通过 winsock 发送的字节数?

如何向 Delphi WinSock HTTP 上传应用程序添加 HTTPS 支持?

同时执行 recv() 和 send() winsock