2014-01-20 129 views
1

我做了一個小測試,從python應用程序(客戶端套接字)發送到C++應用程序(套接字服務器)的整數都是TCP流套接字。我也測試過從Python中的客戶端套接字發送相同的整數到Python中的服務器套接字。Python 3套接字客戶端發送數據和C + +套接字服務器接收數據與偏移?

我做的是我送的4個字節(字符在C++)的陣列,每個char的整數向右移位(>>)這樣的(Python語法):

... 
[my_int >> i & 0xff for i in (24,16,8,0)]: 
... 

的問題是當從python的客戶端套接字發送到服務器套接字在python數據「到達ok」,例如,如果我發送整數1390248303

python服務器套接字首先打印接收到的字節流然後爲它打印其每個字節ascii碼,然後我做:

sum([l[3-i] << 8*i for i in (3,2,1,0)]) 

「重建」的整數,這是結果(這是確定):

RECEIVED: b'R\xdd\x81o' 
82 
221 
129 
111 
RECEIVED: 1390248303 

但C++服務器套接字,其中我做相同的,但與代碼中更詳細的:

... 
int sum = 0; 
int term = 0; 
for(int i = 3;i > -1;i--) 
{ 
    printf("%d\n",msg[3-i]); 
    term = msg[3-i]; 
    //if (term < 0) 
    // term = 256 + term; 
    suma += term << 8*i;     
}; 
printf("Received: %d\n",sum); 
... 

輸出

82 
-35 
-127 
111 
Received: 1373405551 

你看到的是,在中間的2個字節是在中間相應的T 2個字節不同o python輸出中的服務器套接字是什麼?不僅如此,但如果我加256他們變得相同:

-35 + 256 = 221 
-127 + 256 = 129 

這種行爲的原因是什麼?預先感謝任何提示!

這裏是應用程序的代碼:

蟒客戶端套接字:

import socket 
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
client_socket.connect(("localhost", 7000)) 
my_int = 1390248303 
my_bytes = bytearray()   
for e in [my_int >> i & 0xff for i in (24,16,8,0)]: 
    my_bytes.append(e) 
print("To be sent:", my_bytes)  
client_socket.send(my_bytes) 
print("Sent:", my_bytes)  
client_socket.close() 

蟒服務器套接字:

import socket 
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
server_socket.bind(("", 7000)) 
server_socket.listen(5) 

print("TCPServer Waiting for client on port 7000") 

while 1: 
    client_socket, address = server_socket.accept() 
    print("I got a connection from ", address) 
    while 1: 
     data = client_socket.recv(32) 
     print("RECEIVED:",data) 
     l = [] 
     for e in data: 
      l.append(e) 
      print(e) 
     print("RECEIVED:",sum([l[3-i] << 8*i for i in (3,2,1,0)])) 
     if (data == b''): 
      break; 
    break; 

C++服務器套接字:

#define WIN32_LEAN_AND_MEAN 

#include <WinSock2.h> 
#include <WS2tcpip.h> 
#include <stdio.h> 
#include <stdlib.h> 


// link with Ws2_32.lib 
#pragma comment(lib, "Ws2_32.lib") 

#define DEFAULT_PORT "7000" 
//"27015" 
#define DEFAULT_BUFFER_LENGTH 32 
//512 

int main() { 

    WSADATA wsaData; 

    // Initialize Winsock 
    int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 
    if(iResult != 0) 
    { 
     printf("WSAStartup failed: %d\n", iResult); 
     return 1; 
    } 

    struct addrinfo *result = NULL, 
        hints; 

    ZeroMemory(&hints, sizeof(hints)); 
    hints.ai_family = AF_INET;  // Internet address family is unspecified so that either an IPv6 or IPv4 address can be returned 
    hints.ai_socktype = SOCK_STREAM; // Requests the socket type to be a stream socket for the TCP protocol 
    hints.ai_protocol = IPPROTO_TCP; 
    hints.ai_flags = AI_PASSIVE; 

    // Resolve the local address and port to be used by the server 
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); 
    if (iResult != 0) 
    { 
     printf("getaddrinfo failed: %d\n", iResult); 
     WSACleanup(); 
     return 1; 
    } 

    SOCKET ListenSocket = INVALID_SOCKET; 

    // Create a SOCKET for the server to listen for client connections 
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 

    if (ListenSocket == INVALID_SOCKET) 
    { 
     printf("Error at socket(): %d\n", WSAGetLastError()); 
     freeaddrinfo(result); 
     WSACleanup(); 
     return 1; 
    } 

    // Setup the TCP listening socket 
    iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); 

    if (iResult == SOCKET_ERROR) 
    { 
     printf("bind failed: %d", WSAGetLastError()); 
     freeaddrinfo(result); 
     closesocket(ListenSocket); 
     WSACleanup(); 
     return 1; 
    } 

    freeaddrinfo(result); 

    // To listen on a socket 
    if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) 
    { 
     printf("listen failed: %d\n", WSAGetLastError()); 
     closesocket(ListenSocket); 
     WSACleanup(); 
     return 1; 
    } 

    SOCKET ClientSocket; 

    ClientSocket = INVALID_SOCKET; 

    // Accept a client socket 
    ClientSocket = accept(ListenSocket, NULL, NULL); 

    if (ClientSocket == INVALID_SOCKET) 
    { 
     printf("accept failed: %d\n", WSAGetLastError()); 
     closesocket(ListenSocket); 
     WSACleanup(); 
     return 1; 
    } 

    char recvbuf[DEFAULT_BUFFER_LENGTH]; 
    int iSendResult; 

    // receive until the client shutdown the connection 
    do { 
     iResult = recv(ClientSocket, recvbuf, DEFAULT_BUFFER_LENGTH, 0); 
     if (iResult > 0) 
     { 
      char msg[DEFAULT_BUFFER_LENGTH]; 
      memset(&msg, 0, sizeof(msg)); 
      strncpy(msg, recvbuf, iResult);   

      printf("Received: %s\n", msg); 
        //Here is where I implement the python code: 
      //sum([l[3-i] << 8*i for i in (3,2,1,0)])); 
      int sum = 0; 
      int term = 0; 
      for(int i = 3;i > -1;i--) 
      { 
       printf("%d\n",msg[3-i]); 
       term = msg[3-i]; 
       //if (term < 0) 
       // term = 256 + term; 
       sum += term << 8*i;    
      }; 
      printf("Received: %d\n",sum); 

      iSendResult = send(ClientSocket, recvbuf, iResult, 0); 

      if (iSendResult == SOCKET_ERROR) 
      { 
       printf("send failed: %d\n", WSAGetLastError()); 
       closesocket(ClientSocket); 
       WSACleanup(); 

       getchar(); 
       return 1; 
      } 

      printf("Bytes sent: %ld\n", iSendResult); 
     } 
     else if (iResult == 0) 
      printf("Connection closed\n"); 
     else 
     { 
      printf("recv failed: %d\n", WSAGetLastError()); 
      closesocket(ClientSocket); 
      WSACleanup(); 

      getchar(); 
      return 1; 
     } 
    } while (iResult > 0); 

    // Free the resouces 
    closesocket(ListenSocket); 
    WSACleanup(); 

    getchar(); 
    //while (true){}; 
    return 0; 
} 

回答

0

msg[]被宣佈爲char,不保證是unsigned。使用unsigned char

  printf("%d\n",msg[3-i]); 
      term = msg[3-i]; 

投地符號整數的兩個。格式爲有符號整數,使用%uterm被宣佈爲int,使其成爲unsigned int

0

繼@Ante建議,我改變在C++服務器套接字的代碼,我也改變recvbuf爲unsigned char和總和從int到無符號整型的一致性(畢竟我等着接收無符號字符和「重建」一個無符號詮釋),但它也工作,離開recvbuf和總和,因爲他們是。我留下了以前的評論。

問題是,爲了表示一個整數這麼大,我實際上使用了一個無符號整數,並且發送的字節是ASCII範圍的代碼,範圍是0-255(與unsigned char相同範圍),char範圍是 - 儘管如此,套接字並不關心數據類型,它們只是發送二進制數據,所以我得到了無符號的字符,當bein放入char時,它們會「溢出」並變爲負值(從技術上講,這是因爲如何two's complement作品我認爲)。關於更正後的代碼

一些更多的注意事項:

1)本

if (term < 0) 
    term = 256 + term; 

不再是必要的(其實我是手動修復溢出的問題)。

2)我不得不用鑄爲char *(字符),以便能夠使用的recv,strncpy()函數,併發送帶炭作爲參數不無符號字符*。這項工作,我認爲它不hackish,因爲無論是char指針和無符號字符指針都指向內存中具有相同大小的數據類型(8位)。如果這是錯誤的或可能導致不想要的或意外的行爲,請糾正我。

//char recvbuf[DEFAULT_BUFFER_LENGTH]; 
    unsigned char recvbuf[DEFAULT_BUFFER_LENGTH]; 
    int iSendResult; 

    // receive until the client shutdown the connection 
    do { 
     //iResult = recv(ClientSocket, recvbuf, DEFAULT_BUFFER_LENGTH, 0); 
     iResult = recv(ClientSocket, (char *)recvbuf, DEFAULT_BUFFER_LENGTH, 0); 
     if (iResult > 0) 
     { 
      //char msg[DEFAULT_BUFFER_LENGTH]; 
      unsigned char msg[DEFAULT_BUFFER_LENGTH]; 
      memset(&msg, 0, sizeof(msg)); 
      //strncpy((msg, recvbuf, iResult); 
      strncpy((char *)msg, (char *)recvbuf, iResult);   

      printf("Received: %s\n", msg); 

      //sum([l[3-i] << 8*i for i in (3,2,1,0)])); 
      //int sum = 0; 
      unsigned int sum = 0; 
      //int term = 0; 
      unsigned int term = 0; 
      for(int i = 3;i > -1;i--) 
      { 
       //printf("%d\n",msg[3-i]); 
       printf("%u\n",msg[3-i]); 
       term = msg[3-i];      
       sum += term << 8*i;    
      }; 
      //printf("Received: %d\n",sum); 
      printf("Received: %u\n",sum); 

      //iSendResult = send(ClientSocket, recvbuf, iResult, 0); 
      iSendResult = send(ClientSocket, (char *) recvbuf, iResult, 0); 
相關問題