2013-12-16 80 views
1

我的頭文件structure.h中有以下結構。現在我需要在我的main.c文件中使用此結構。在TCP/IP套接字中發送客戶端到服務器的結構

我需要填充一些值的結構,我需要從TCP/IP客戶端發送到同一系統上的TCP/IP服務器。

#ifndef STRUCTURE_H 
#define STRUCTURE_H 

typedef struct 
{ 
    unsigned int variable3; 
    char variable4[8]; 
}NUMBER_ONE,*PNUMBER_ONE; 


typedef struct 
{ 
    unsigned int variable5; 
    char variable6[8]; 
}NUMBER_TWO,*PNUMBER_TWO; 

typedef struct 
{ 
    char name[32]; 
    unsigned int a; 
    unsigned int b; 
    NUMBER_ONE variable1; 
    NUMBER_TWO variable2; 
}NUMBER_THREE,*PNUMBER_THREE; 

#endif 

我都試過,但,我不擅長於C,所以請誰能告訴我該怎麼做,通過採取上述結構作爲例子嗎?直到套接字連接建立對我來說是好的, 但建立連接後,如何將這個結構從客戶端發送到服務器?

我在Linux Ubuntu 12.04系統中這樣做。

+2

我不會那樣做,因爲不同的機器可能有不同的字節順序(Big Endian/Little Endian),結構打包等等,所以結構可能不會在另一邊正確解碼。您應該更好地使用交換格式,您可以設計自己的或使用多種現有格式之一(JSON,BSON,XML,AMF ...) – SirDarius

+0

不要將結構用作網絡協議。你引入了六打左右的依賴關係。以八位字節定義一個有線協議,並編寫代碼發送和接收它。 – EJP

回答

2

當使用套接字使用三種方式發送信息:

1)固定大小的信息(我們將使用它,加上假設我們正在寫在同一臺機器字節順序匹配上).Simply,如我們將發送100個字節和上接收我們將讀取100字節

2)message.len +消息(第一我們發送消息len個然後消息本身。用於二進制發送接收大部分)

3)標記物方法(大多用於發送文本消息或命令,用\ n換行標記)

接下來代表我們的數據(序列化)。用c導致c很容易,我們可以直接編寫我們的對象並且不需要額外的努力就可以得到它。對象將和內存中的一樣。

// PNUMBER_THREE structAddr; 
    send(socket_id, structAddr, sizeof(NUMBER_THREE), 0); 

write(socket_id, structAddr, sizeof(NUMBER_THREE)); 

或更安全的

write_socket(socket_id, structAddr, sizeof(NUMBER_THREE)); 
//It is safer to do so though we are using blocking mode 
int write_socket(int fd,const char *buf,int len){ 
    int currentsize=0; 
    while(currentsize<len){ 
     int count=write(fd,buf+currentsize,len-currentsize); 
     if(count<0) return -1; 
     currentsize+=count; 
    } 
    return currentsize; 
} 

閱讀,我們將使用相同的結構再加上它必須滿足條件時,sizeof(NUMBER_THREE)==SizeInsideClient //SizeInsideClient is sizeof on client SizeInsideClient=sizeof(NUMBER_THREE)

//SizeInsideClient structure size on client program 
    assert(sizeof(NUMBER_THREE)==SizeInsideClient); 
    readblock(socket_id,structAddr,sizeof(NUMBER_THREE)); 

    int readblock(int fd, char* buffer, int len) { 
     int ret = 0; 
     int count = 0; 
     while (count < len) { 
      ret = read(fd, buffer + count, len - count); 
      if (ret <= 0) { 
       return (-1); 
      } 
      count += ret; 
     } 
     return count; 

    } 
+0

只需一個簡單的發送/寫入電話即可完成工作。請仔細閱讀有關套接字的相關手冊頁。 – alk

+0

這是一個快速和醜陋的方式,只要你的手臂有一個警告列表。如果這是除了實驗以外的任何其他內容,請找到一種編組和解除數據嵌入一些元數據(以及可能的版本信息)的方法。 – Speed8ump

+0

@qwr我如何在接收端(在服務器端)接收該消息。你能解釋我嗎,因爲我不知道如何序列化和反序列化結構數據,你可以通過示例來展示。 – user3094304

0

簡單的例子,沒有錯誤檢查:

服務器

struct sockaddr_in serv_addr; 

listenfd = socket(AF_INET, SOCK_STREAM, 0); 

serv_addr.sin_family = AF_INET; 
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
serv_addr.sin_port = htons(5000); 
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 

listen(listenfd, 10); 

while(1) 
{ 
    connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); 
    snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks)); 
    write(connfd, sendBuff, strlen(sendBuff)); 
    close(connfd); 
    sleep(1); 
} 

客戶

struct sockaddr_in serv_addr; 

sockfd = socket(AF_INET, SOCK_STREAM, 0); 

serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(5000); 

inet_pton(AF_INET, argv[1], &serv_addr.sin_addr); 
connect(sockfd, 
(struct sockaddr *)&serv_addr, sizeof(serv_addr)) 

    while ((n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0) 
    { 
     recvBuff[n] = 0; 
     if(fputs(recvBuff, stdout) == EOF) 
     { 
      printf("\n Error : Fputs error\n"); 
     } 
    } 

陷阱

是不是「安全」,所以發送普通結構。遲早你會處理字節序(字節順序),打包(即使使用#pragma pack也是一個問題),以及像'int'這樣的大小可能會在不同平臺之間變化。

相關問題