2014-01-20 121 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); 
相关问题