C ++ Winsock2以字节顺序发送整数

时间:2012-06-02 20:35:08

标签: c++ sockets

我一直在寻找一种使用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);

}

3 个答案:

答案 0 :(得分:3)

问题在于:

int bytes = recv(server, (char*) &int_data, sizeof(int), 0);

应该是:

int bytes = recv(client, (char*) &int_data, sizeof(int), MSG_WAITALL);

其他一些挑剔的事情,并没有引起你的问题,但你应该知道:

  1. 不要将服务器套接字绑定到10.0.0.5。绑定为0(INADDR_ANY)。这样,当您在IP地址为10.0.0.6的计算机上运行代码时,代码仍然有效。

  2. 使用htonl(),htons(),ntohs()和ntohl()与big-endian框进行互操作。

  3. 始终检查套接字调用的返回值。如果recv返回0或-1,则表示远程端已断开连接。 (0技术上意味着客户端已停止发送,但除非您正在关闭半关闭的东西,否则表示他已断开连接。)

  4. TCP套接字不是面向消息的,它们是面向流的。也就是说,仅仅因为你告诉recv()得到N个字节,并不意味着它将返回N个字节。 IP分段,TCP分段和其他因素可以使recv()返回部分数据。根据需要使用MSG_WAITALL标志。

答案 1 :(得分:1)

你自己几乎不可能做到这一点。不是从代码开始,而是从协议规范开始。您可以查看使用TCP的现有协议的规范,例如HTTP,IMAP等,以查看协议规范应包含的内容。

协议规范应解释在字节级别发送或接收的所有内容。它应该解释如何建立和拆除连接。它应解释如何从任一端检测到死连接。如果协议具有应用层消息,则应解释它们是如何分隔的以及接收方如何找到消息的末尾。它应该指定谁发送的时间。

然后,调试很容易。请遵循以下流程图:

1)服务器是否遵循规范?如果没有,服务器就坏了。

2)客户是否遵循规范?如果没有,客户端就会崩溃。

3)如果它仍然不起作用,则说明会被破坏。

这样可以确保服务器和客户端协同工作。如果他们不这样做,就可以知道哪一方需要修复。

草拟协议规范只需要一两个小时,我保证节省的时间将超过它。所有这一切都是有一次你在某些东西不起作用时改变了错误的结局(然后发现很多东西都是新破坏的,因为你修复了一个正确的地方)来支付所花费的时间。另外,作为奖励,可以进行其他实施。

答案 2 :(得分:0)

我也遇到了这个问题,我注意到我的客户连接都没有。

尝试保存connect()和recv()返回的值,确保其&gt; -1或打印出一些错误。