簡體   English   中英

在c中發送緩沖區長度和緩沖區

[英]Sending buffer length and buffer over socket in c

我正在嘗試使用C將字符串發送到服務器應用程序,但我遇到了麻煩。 我對網絡編程很新,我認為我的代碼正在咆哮錯誤的樹。

該消息應該是消息長度+消息,並且由python服務器在另一側解壓縮(buf是原始傳入數據):

msg_len_bytes = buf[0:4]
msg_len = struct.unpack("!L", msg_len_bytes)[0]

表示網絡字節順序,L表示無符號長整數。

發送常規字符串相當簡單。 發送(襪子,消息,strlen(消息),0);

但是添加消息長度我無法理解。 這是我的客戶端到目前為止的代碼:

struct msgstruct {
        uint32_t length;
        char send_data[4096];
};

int main()

{
    int sock;
    struct msgstruct message;
    char data[4096] = "<MOP><test/></MOP>";

    for ( int i = 0; i < strlen(data); i++ ) {
      message.send_data[i] = data[1];
    }

    struct hostent *host;
    struct sockaddr_in server_addr;

    unsigned long buflen = sizeof(message.send_data);
    uint32_t bufsend = htonl(buflen);

    message.length = bufsend;

    host = gethostbyname("127.0.0.1");

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Socket");
        exit(1);
    }

    server_addr.sin_family = AF_INET;     
    server_addr.sin_port = htons(12998);   
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    bzero(&(server_addr.sin_zero),8); 


    if (connect(sock, (struct sockaddr *)&server_addr,
                sizeof(struct sockaddr)) == -1) {
        perror("Connect");
        exit(1);
    }

    if(send(sock, message.length + message.send_data, sizeof(message), 0) == -1){
        printf("\nSocket error.");
        exit(1);
    }
    return 0;
}

我嘗試了一些變化,但我總是遇到套接字錯誤。 是因為我在派遣的第二個爭論中混合了類型嗎? 如果我嘗試發送結構,我會收到編譯錯誤。

您可以使用2個后續發送:

send(sock, &message.length, sizeof(message.length), 0);
send(sock, message.send_data, message.length*sizeof(char), 0);

或者更好地准備前4個字節的緩沖區作為消息長度:

char buff[MAX_BUFF] = "";
int  len_disp = sizeof(message.length);
memcpy(buff, &message.length, len_disp);
memcpy(&buff[len_disp], &message.length, message.length*sizeof(char));
send(sock, buff, message.length*sizeof(char) + len_disp, 0);

編輯:對於小消息評論 - 禁用Nagle的算法。

BOOL bNagleEnabled = FALSE;
if(setsockopt(sAccept, IPPROTO_TCP, TCP_NODELAY, (char *)&bNagleEnabled, sizeof(BOOL)))
{
  ReportError("Setting TCP_NODELAY socket option failed");
  return -2;
}

錯誤在此代碼中:

send(sock, message.length + message.send_data, sizeof(message), 0)

發送的原型是:

ssize_t send(int s, const void *buf, size_t len, int flags);

請注意,參數2是指針。 在您的代碼中,您已將其作為長度(類型uint32_t)添加到緩沖區(Type char *)。 這個添加將導致char *,(指向char的指針),但是指向不可預測且無意義的內存區域的指針。

要獲得指向緩沖區的指針,您需要:

send(sock, &message, sizeof(message), 0)

請注意,由於填充問題,獲取結構的地址不可移植或始終是可取的。 但在典型的32位架構上,這應該沒問題。

這將從消息struct開始發送數據,但發送4100(4096 + 4)個字節! 我不認為你打算發這么多。 第3個參數表示要發送的字節數,應設置為:

sizeof(uint32_t) + strlen(data);  // 4-byte Integer + Length of the data "<MOP><test/></MOP>"

請注意,這包括空終止的數據,但是,你的for循環的初始沒有可以復制一個空終結者

(如果你想要null終止符,那么讓你的初始for循環轉到strlen(data)+1 ,並在其他地方使用strlen(data)+1 )。

理想情況下,您應該將strlen(數據)緩存到本地變量,而不是調用它。 (你也在inital for-loop中反復調用strlen)。

您的最終陳述將如下所示:

if(send(sock, &message, sizeof(uint32_t)+strlen(data), 0) == -1){
    printf("\nSocket error.");
    exit(1);
}

試試看,讓我知道它是怎么回事。

將數據復制到message實例中的循環被破壞,它有一個1應該有一個i

send()的第二個參數應該是指向要發送的第一個字節的指針。 相反,你給它一個大端數的總和(如果你的平台不是big-endian,那將是非常錯誤的)和隨機數組基地址。 這是錯的。

你需要:

if(send(sock, &message, sizeof message.length + strlen(data), 0) == -1) {

還有一些其他的困惑,你似乎“想”總是發送完整的4K,而不僅僅是必要的金額。

基本上一切都應該通過套接字來轉換緩沖區和發送/接收。 通常我做的是:

 //Send
 memcpy(buffer, &structure_u_defined, sizeof(structure_u_defined));
 send(&sock, buffer,...);// lol I am using a public pc

 //receive
 recv(&sock, buffer,...);
 memcpy(&structure_u_defined_for_receive, buffer, sizeof(buffer));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM