如何通过Windows winsock send()发送包含指针的结构?

时间:2014-01-20 15:31:14

标签: c++ c sockets

我正在使用Winsock在C ++中创建服务器/客户端程序。

  • SLoginSid打包到char array

  • Sidbuf[0]SLoginbuf[1]

  • Sid来自buf[0]

Slogin获取buf[1]的问题。 这是我的代码:

#include <Winsock2.h>
#include <Windows.h>
#include <stdio.h>
#include <string>
#pragma comment (lib, "ws2_32.lib")

struct Sid
{
    unsigned int id;
};

struct SLogin
{
    char * login;
    char * password;
};

struct SloginRet
{
    bool OkOrFalse;
};

SOCKET sSocket = INVALID_SOCKET;
void Connect()
{

    WSAData data;
    if(WSAStartup(MAKEWORD(2,2), &data) != NO_ERROR)
    {
        printf("WSAStartup: %d\n", WSAGetLastError());
        return;
    }

    sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sSocket == INVALID_SOCKET)
    {
        printf("socket: %d\n", WSAGetLastError());
        return;
    }


    sockaddr_in service;
    memset(&service, 0, sizeof(service));
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr("127.0.0.1");
    service.sin_port = htons(5000);

    connect(sSocket, (SOCKADDR*)&service, sizeof(service));


    Sid idd;
    idd.id = 1001;
    char buffer[1];

    memcpy(&buffer[0], &idd, sizeof(idd));

    Sid ida;
    memcpy( &ida, &buffer[0], sizeof(int));


    printf("%d %d\n", ida.id, sizeof(buffer));

    SLogin login;

    login.login = "Vitor";
    login.password = "123";

    memcpy(&buffer[1], &login, sizeof(char));

    SLogin *pLogin = (SLogin*)buffer[1]; 
    printf("%s", pLogin->login);
//  send(sSocket, buffer,strlen(buffer), 0);

    closesocket(sSocket);
    WSACleanup();
}


void main()
{
    Connect();
    system("pause");
}


Server Recv:

recv(socket,buffer,1,0);
char buffer[1]; //receive

Sid id;
memcpy(&id, &buffer[0],sizeof(buffer[0]));

SLogin login;
memcpy(&login, &buffer[1],sizeof(buffer[1]));

使用memcpySid复制到char array buf[0],(char buf[1]) 并从buf获得Sid

SLogin上的错误: 我使用memcpy SLogin登录buf[1]并从buf获取Slogin但有问题。

1 个答案:

答案 0 :(得分:0)

您没有分配足够的内存。您的buffer大小只有1 charsizeof(char)是1个字节),但您尝试将12个字节填入其中(sizeof(Sid)为4个字节,{{1是8个字节)。即使您确实分配了足够的内存,它仍然无法工作,因为sizeof(SLogin)包含指向外部内存的指针,您不会将其序列化为可以安全发送/接收的连续格式。

尝试更像这样的东西:

SLogin

#pragma pack(push, 1)
// or equivilent for your compiler

struct Sid
{
    unsigned int id;
};

struct SLogin
{
    char login[20];
    char password[20];
};

#pragma pack(pop)
// or equivilent for your compiler

#include <Winsock2.h>
#include <Windows.h>
#include <stdio.h>
#include <string>
#pragma comment (lib, "ws2_32.lib")

SOCKET sSocket = INVALID_SOCKET;
void Connect()
{

    WSAData data;
    int err = WSAStartup(MAKEWORD(2,2), &data);
    if (err != NO_ERROR)
    {
        printf("WSAStartup: %d\n", err);
        return;
    }

    sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sSocket == INVALID_SOCKET)
    {
        printf("socket: %d\n", WSAGetLastError());
        return;
    }

    sockaddr_in service;
    memset(&service, 0, sizeof(service));
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr("127.0.0.1");
    service.sin_port = htons(5000);

    if (connect(sSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
    {
        printf("connect: %d\n", WSAGetLastError());
        closesocket(sSocket);
        return;
    } 

    char buffer[sizeof(Sid)+sizeof(SLogin)];

    Sid *pSid = (Sid*) &buffer[0];
    PSid->id = 1001;

    printf("%ul\n", pSid->id);

    SLogin *pLogin = (SLogin*) &buffer[sizeof(Sid)];
    strncpy(pLogin->login, "Vitor", 20);
    strncpy(pLogin->password, "123", 20);

    printf("%.20s\n", pLogin->login);

    //send(sSocket, buffer, sizeof(buffer), 0);

    closesocket(sSocket);
    WSACleanup();
}

void main()
{
    Connect();
    system("pause");
}