socket编程中recv函数接收到的字符串乱码解决方法

最近闲来无事,研究一下socket编程,尝试写一个邮箱服务器。但是在socket连接成功之后,使用recv()函数时出现了问题——recv接收到的字符串竟然是乱码,如下所示。

LiHua 烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫葺葺sT▍?

调试了很久,一直在奔溃的边缘徘徊,最后发现竟然是个很小的错误导致的。果然,粗心是魔鬼。下面分享一下艰难的心路旅程,想直接看解决方法的小伙伴也可以跳过代码和图案往后看。(出于私心不建议这么做)

1.服务器端接收发送部分代码,通过客户端输入获得登录名和登录密码。

char User_Name[40];
char Passward[40];

char SendInf_1[40]; // "LogUp a UserName:" 
cin >> SendInf_1;
send(socket_accept, SendInf_1, 40, 0);
recv(socket_accept, User_Name, 40, 0);

char SendInf_2[40];// "Input Your Password:" 
cin >> SendInf_2;
send(socket_accept, SendInf_2, 40, 0);
recv(socket_accept, Passward, 40, 0);

2.客户端接收发送部分代码,为简化篇幅稍作删减。

char recv_buf[100];
char send_buf[100];
for(int i = 0; i < 2; i++){
	recv(s_server, recv_buf, 100, 0);
	cin >> send_buf;
	send(s_server, send_buf, 100, 0);
}

3.服务器端输入InputYourName和InputPassword。

在这里插入图片描述

4.客户端输入LiHua和123456789 在这里插入图片描述
5.结果像上面的那样,recv到的字符串变量User_Name = "LiHua",而”Password"却是一串乱码。

出错原因我众里寻他千百度,慕然回首,最终却发现是我的客户端与服务端传送的字符串不匹配。客户端发送的字符串send_buf长度为100字节;而服务端用于接收的字符串User_Name长度却为40字节,完全不够存放发送过来的数据。

在微软官网的winsock.h头文件使用手册中关于recv函数有下面这样一段说明。

If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recv generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost; for reliable protocols, the data is retained by the service provider until it is successfully read by calling recv with a large enough buffer.
如果数据报或消息大于指定的缓冲区,缓冲区将被数据报的第一部分填满,recv将生成错误WSAEMSGSIZE。对于不可靠的协议(例如UDP),多余的数据会丢失;对于可靠的协议,数据由服务提供商保留,直到通过调用具有足够大缓冲区的recv成功读取。

传送门——> recv function (winsock.h)

我么这里建立的TCP连接是可靠协议。也就是说recv的数据超过缓冲区大小buf时,超出的部分会保留,直到被下一个recv函数提取出来,另一端对应的send函数不再发挥作用,因此导致我的代码第二次接收出现字符串变量乱码,而不是我想要的123456789字符串值。

于是,我把发送和接收的字符串长度改成一样就可以了!!(如上客户端代码中所有的100改成40即可)

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
send函数recv函数是VC++Socket编程最常用的两个函数,它们分别用于发送数据和接收数据。 send函数的原型如下: ```c++ int send( SOCKET s, const char* buf, int len, int flags ); ``` 参数说明: - s:需要发送数据的Socket。 - buf:指向包含要发送数据的缓冲区的指针。 - len:要发送的数据的字节数。 - flags:调用方式标志。 返回值说明: - 成功:返回实际发送的字节数。 - 失败:返回SOCKET_ERROR。 recv函数的原型如下: ```c++ int recv( SOCKET s, char* buf, int len, int flags ); ``` 参数说明: - s:需要接收数据的Socket。 - buf:指向接收数据的缓冲区的指针。 - len:要接收的数据的最大字节数。 - flags:调用方式标志。 返回值说明: - 成功:返回实际接收的字节数。 - 失败:返回SOCKET_ERROR。 send和recv函数的使用方法如下: ```c++ char sendbuf[] = "Hello, world!"; int sendbuflen = sizeof(sendbuf); int sentbytes = 0; sentbytes = send(sock, sendbuf, sendbuflen, 0); if (sentbytes == SOCKET_ERROR) { // 发送失败 } char recvbuf[1024]; int recvbuflen = sizeof(recvbuf); int receivedbytes = 0; receivedbytes = recv(sock, recvbuf, recvbuflen, 0); if (receivedbytes == SOCKET_ERROR) { // 接收失败 } ``` 使用send和recv函数时需要注意以下几点: - send和recv函数都是阻塞式的,即程序会一直等待直到发送或接收完所有数据。 - 如果发送或接收的数据量比较大,需要多次调用send或recv函数。 - 如果发送或接收的数据量比较小,建议使用TCP_NODELAY选项关闭Nagle算法,以提高发送和接收的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值