最近闲来无事,研究一下socket编程,尝试写一个邮箱服务器。但是在socket连接成功之后,使用recv()函数时出现了问题——recv接收到的字符串竟然是乱码,如下所示。
LiHua 烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫葺葺sT▍?
调试了很久,一直在奔溃的边缘徘徊,最后发现竟然是个很小的错误导致的。果然,粗心是魔鬼。下面分享一下艰难的心路旅程,想直接看解决方法的小伙伴也可以跳过代码和图案往后看。(出于私心不建议这么做)
1.服务器端接收发送部分代码,通过客户端输入获得登录名和登录密码。
char User_Name[40];
char Passward[40];
char SendInf_1[40];
cin >> SendInf_1;
send(socket_accept, SendInf_1, 40, 0);
recv(socket_accept, User_Name, 40, 0);
char SendInf_2[40];
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即可)
|