2015-09-03 38 views
1

我一直在研究一個使用TCP套接字與服務器進行通信的小型純C客戶端應用程序(我的第一個:/)。服務器發送一個數據包(C結構),其中第一個字節包含數據包的大小。使用無符號字符而不是字符,因爲它的範圍

問題是服務器使用無符號字符來表示數據包的大小,因爲字符有符號(從-128到+127),+127不足以表示在某些數據包中可能高達255的大小。 =>我需要一個unsigned char緩衝區;

在Linux中,的recv()函數的第二個參數是無效*,這意味着能聲明一個void *緩衝液和沒有問題。但是Windows(MinGW)中的recv()具有char *而不是void *。這給我的警告「參數類型不匹配:不兼容的指針類型‘字符*’和‘無符號字符*’」

是否有可能解決這個問題?這是代碼。謝謝。 PS:我正在使用非阻塞套接字。

int recvsize = 0; 
unsigned char tmpsize; 
int index = 0; 
unsigned char *buffer; 

while (1) { 

    recvsize = recv(server, &tmpsize, sizeof(unsigned char), 0); // every packet starts with one byte where is its length 

    if (recvsize > 0) { 
     buffer = malloc(tmpsize * sizeof(unsigned char)); //memory allocation according to the size of packet 
     buffer[0] = tmpsize--; //get back the size value to the buffer 
     recvsize = 0; 


     do { //loop over and over until you do not have all bytes of the packet 
      recvsize = recv(server, &buffer[++index], tmpsize, 0); 

      if (recvsize == 0) 
       break; 


      tmpsize -=recvsize; 
      index += recvsize; 

     } while (tmpsize != 0); 

    } 
sleep(50); 
} 
+1

'char'可能會在您的平臺上簽名。標準將其留給實現,一般來說,當在不同系統間傳輸數據(大多數時候也在同一系統中)時,使用'stdint.h'類型和正確的序列化是首選方式。否則,一個tarpit正在等待。 – Olaf

+0

注意:'sizeof(unsigned char)'總是1,所以不需要'... * sizeof(unsigned char)'。如果代碼想通過變量的大小來注意縮放,建議'buffer = malloc(tmpsize * sizeof * buffer)' – chux

回答

2

只需將指針轉換爲正確的類型即可。所以使用:

(char *) (&buffer[++index]) 

另外,爲什麼你要通過在睡眠循環中重複一個非阻塞操作來創建阻塞方案?要麼使用阻塞套接字,要麼使用非阻塞套接字,但不要在中間創建一些虛假事物。 (例如,如果惡意或慢速客戶端只向您發送一個字節,您將轉至recv。)

最後,爲什麼在第一次調用recv時只讀取一個字節?無論如何你需要其餘的數據,那麼爲什麼要讓內核以微小的滴落給你?爲什麼不盡可能多地讀取字節,並且幸運的是,避免需要第二次調用recv

+0

是的,我的錯誤! – cdonts

+0

「你爲什麼只在第一次讀取時只讀一個字節」嗯,也許可能有多條消息,並且通過閱讀「儘可能多的字節」,可能無法獲取多個或部分消息,然後必須進行管理? – chux

+1

@chux是的,當然。這就是TCP的性質。現在,他迫使內核去做。他已經處理了部分消息。 –

相關問題