2014-01-20 60 views
0

我使用Winsock在C++中創建服務器/客戶端程序。如何通過Windows發送包含指針的結構winsock send()?

  • 包裝SLoginSidchar array

  • Sidbuf[0]SLoginbuf[1]

  • Sid從獲得buf[0]

問題從buf[1]得到Slogin。 這是我的代碼:來自BUF OK

#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])); 

使用memcpy複製Sidchar array buf[0]char buf[1]) 並獲得Sid

我的錯誤上SLogin: 我複製與memcpySLogin登錄buf[1],並從BUF Slogin有問題的。

+0

請告訴我們的錯誤。 – noelicus

+0

不要使用結構作爲網絡協議。您至少引入了六個我在其他地方類似問題中列舉的依賴項。以八位字節定義一個應用協議,併爲自己寫一個庫來發送和接收它。 – EJP

回答

0

您沒有分配足夠的內存。您的buffer的大小僅爲1 charsizeof(char)爲1個字節),但您試圖填充12個字節(sizeof(Sid)爲4個字節,sizeof(SLogin)爲8個字節)。即使你確實分配了足夠的內存,它仍然不起作用,因爲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"); 
} 

char buffer[256]; //receive 
int numBytes = recv(socket, buffer, sizeof(buffer), 0); 
...  
Sid *pSid = (Sid*) &buffer[0]; 
SLogin *pLogin = (SLogin*) &buffer[sizeof(Sid)];