繁体   English   中英

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

[英]C++ Winsock2 sending integers with byte order

我一直在寻找一种使用Winsock2通过Windows套接字发送整数的方法。 我已经研究了人们已经对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);

}

这是问题所在:

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标志。

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

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

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

1)服务器是否遵循规范? 如果不是,则服务器损坏。

2)客户是否遵守规范? 如果不是,则客户端损坏。

3)如果仍然无法正常工作,则说明规格被破坏。

这使得可以确保服务器和客户端一起工作。 而当他们不这样做时,就可以知道需要修复哪一侧。

制定协议规范只需要一两个小时,我保证您节省的时间将是值得的。 它所需要的只是一次,当某些事情不起作用时,您改变了错误的结局(然后发现很多事情是新破裂的,因为您修复了一个正确的地方),以花时间支付。 另外,作为奖励,然后可以进行其他实现。

我也被困在这个问题上,我注意到我的客户甚至没有连接。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM