我一直在寻找一种使用Winsock2通过Windows Socket发送整数的方法。我已经查看了人们在stackoverflow上提出的问题(如果不是全部的话)。
这是我为客户端发送的整数:
struct struct_var
{
int Packet;
int Number;
};
struct_var *arraystruct;
arraystruct = (struct_var *) malloc(sizeof(struct_var));
(*arraystruct).Packet = 100;
(*arraystruct).Number = 150;
int bytes = send(client,(char*)arraystruct,sizeof(*arraystruct),0);`
我也尝试使用以下方式发送:
int int_data = 4;
int bytes = send(server, (char*) &int_data, sizeof(int), 0);`
这是在另一个stackoverflow问题上推荐的 这是接收方,也建议:
int int_data;
int bytes = recv(server, (char*) &int_data, sizeof(int), 0);
cout << int_data;`
当我运行这些时,我从命令行得到的输出是:-858993460
有谁知道为什么会这样?
我还希望它具有正确的字节顺序,因为它将通过多种计算机发送。 在此先感谢谁能帮助我
完整服务器代码:
int main() {
WSADATA wsaData;
WORD version;
int error;
version = MAKEWORD(2, 0);
error = WSAStartup(version, &wsaData);
if ( error != 0 )
{
return FALSE;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 0 )
{
WSACleanup();
return FALSE;
}
SOCKET server;
server = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(5555);
if (bind( server, (SOCKADDR*)&sin, sizeof(sin) ) == SOCKET_ERROR ){
DWORD ec=WSAGetLastError();
cerr << hex << "bind ERROR" << ec << endl;
return FALSE;
}
if ( listen( server, SOMAXCONN ) == SOCKET_ERROR ) {
DWORD ec=WSAGetLastError();
cerr << hex << "listen ERROR" << ec << endl;
return FALSE;
}
SOCKET client;
int length;
while(1) {
if ( listen( server, SOMAXCONN ) == SOCKET_ERROR ) {
DWORD ec=WSAGetLastError();
cerr << hex << "listen ERROR" << ec << endl;
return FALSE;
}
length = sizeof sin;
client = accept( server, (SOCKADDR*)&sin, &length );
cout << "Client connected" << endl;
cout << "Sending Instructions..." << endl;
int int_data;
int bytes;
bytes = recv(client, (char*) &int_data, sizeof(int), 0);
cout << int_data << endl;
}
}
}
完整的客户代码:
int main() {
WSADATA wsaData;
WORD version;
int error;
version = MAKEWORD(2, 0);
error = WSAStartup(version, &wsaData);
if ( error != 0 )
{
return FALSE;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 0 )
{
WSACleanup();
return FALSE;
}
SOCKET client;
client = socket( AF_INET, SOCK_STREAM, 0 );
sockaddr_in sin;
memset( &sin, 0, sizeof sin );
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_port = htons(5555);
if ( connect(client, (SOCKADDR*)(&sin), sizeof sin ) == SOCKET_ERROR ){
return FALSE;
}
int int_data = 4;
int bytes = send(client, (char*) &int_data, sizeof(int), 0);
}
答案 0 :(得分:3)
问题在于:
int bytes = recv(server, (char*) &int_data, sizeof(int), 0);
应该是:
int bytes = recv(client, (char*) &int_data, sizeof(int), MSG_WAITALL);
其他一些挑剔的事情,并没有引起你的问题,但你应该知道:
不要将服务器套接字绑定到10.0.0.5。绑定为0(INADDR_ANY)。这样,当您在IP地址为10.0.0.6的计算机上运行代码时,代码仍然有效。
使用htonl(),htons(),ntohs()和ntohl()与big-endian框进行互操作。
始终检查套接字调用的返回值。如果recv返回0或-1,则表示远程端已断开连接。 (0技术上意味着客户端已停止发送,但除非您正在关闭半关闭的东西,否则表示他已断开连接。)
TCP套接字不是面向消息的,它们是面向流的。也就是说,仅仅因为你告诉recv()得到N个字节,并不意味着它将返回N个字节。 IP分段,TCP分段和其他因素可以使recv()返回部分数据。根据需要使用MSG_WAITALL标志。
答案 1 :(得分:1)
你自己几乎不可能做到这一点。不是从代码开始,而是从协议规范开始。您可以查看使用TCP的现有协议的规范,例如HTTP,IMAP等,以查看协议规范应包含的内容。
协议规范应解释在字节级别发送或接收的所有内容。它应该解释如何建立和拆除连接。它应解释如何从任一端检测到死连接。如果协议具有应用层消息,则应解释它们是如何分隔的以及接收方如何找到消息的末尾。它应该指定谁发送的时间。
然后,调试很容易。请遵循以下流程图:
1)服务器是否遵循规范?如果没有,服务器就坏了。
2)客户是否遵循规范?如果没有,客户端就会崩溃。
3)如果它仍然不起作用,则说明会被破坏。
这样可以确保服务器和客户端协同工作。如果他们不这样做,就可以知道哪一方需要修复。
草拟协议规范只需要一两个小时,我保证节省的时间将超过它。所有这一切都是有一次你在某些东西不起作用时改变了错误的结局(然后发现很多东西都是新破坏的,因为你修复了一个正确的地方)来支付所花费的时间。另外,作为奖励,可以进行其他实施。
答案 2 :(得分:0)
我也遇到了这个问题,我注意到我的客户连接都没有。
尝试保存connect()和recv()返回的值,确保其&gt; -1或打印出一些错误。