【问题标题】:Differences between C and Python socketsC 和 Python 套接字之间的区别
【发布时间】:2020-10-18 04:09:10
【问题描述】:

我正在使用带有套接字的 C 程序。我找到了一个与我的程序一起使用的代理 python 脚本:


import threading
import serial
import socket


def setup():
    """
    This function sets up the variables needed, including the serial port,
    and it's speed/port settings, listening socket, and localhost adddress.
    """
    global clisock, cliaddr, svrsock, ser
    # Change this to the COM port your XBee Cellular module is using.  On
    # Linux, this will be /dev/ttyUSB#
    comport = '/dev/ttyAMA0'
    # This is the default serial communication speed of the XBee Cellular
    # module
    comspeed = 9600
    buffer_size = 4096  # Default receive size in bytes
    debug_on = 0  # Enables printing of debug messages
    toval = None  # Timeout value for serial port below
    # Serial port object for XBCell modem
    ser = serial.Serial(comport,comspeed,timeout=toval)
    # Listening socket (accepts incoming connection)
    svrsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # Allow address reuse on socket (eliminates some restart errors)
    svrsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    clisock = None
    cliaddr = None  # These are first defined before thread creation
    addrtuple = ('localhost', 1881)  # Address tuple for localhost
    # Binds server socket to localhost (allows client program connection)
    svrsock.bind(addrtuple)
    svrsock.listen(1)  # Allow (1) connection


def ComReaderThread():
    """
    This thread listens on the defined serial port object ('ser') for data
    from the modem, and upon receipt, sends it out to the client over the
    client socket ('clisock').
    """
    global clisock
    while (1):
        resp = ser.read()  ## Read any available data from serial port
        print("Received {} bytes from modem.".format(len(resp)))

        clisock.sendall(resp)  # Send RXd data out on client socket
        print("Sent {} byte payload out socket to client.".format(len(resp)))


def SockReaderThread():
    """
    This thread listens to the MQTT client's socket and upon receiving a
    payload, it sends this data out on the defined serial port ('ser') to the
    modem for transmission.
    """

    global clisock
    while (1):
        data = clisock.recv(4096)  # RX data from client socket
        # If the RECV call returns 0 bytes, the socket has closed
        if (len(data) == 0):
            print("ERROR - socket has closed.  Exiting socket reader thread.")
            return 1  # Exit the thread to avoid a loop of 0-byte receptions
        else:
            print("Received {} bytes from client via socket.".format(len(data)))
            print("Sending payload to modem...")
            bytes_wr = ser.write(data)  # Write payload to modem via UART/serial
            print("Wrote {} bytes to modem".format(bytes_wr))

def main():
    setup()  # Setup the serial port and socket
    global clisock, svrsock
    if (not clisock):  # Accept a connection on 'svrsock' to open 'clisock'
        print("Awaiting ACCEPT on server sock...")
        (clisock,cliaddr) = svrsock.accept()  # Accept an incoming connection
        print("Connection accepted on socket")
    # Make thread for ComReader
    comthread = threading.Thread(target=ComReaderThread)
    comthread.start()  # Start the thread
    # Make thread for SockReader
    sockthread = threading.Thread(target=SockReaderThread)
    sockthread.start()  # Start the thread

main()

我尝试在 C 中执行相同的代理脚本

#include "project.h"
#include <sys/socket.h> 
#include <arpa/inet.h> 

int fd,baudrate=9600,sock,new_socket;
struct sockaddr_in serv_addr, client;

int setup(){
    
    int opt=1;
    sock=0;
    if(wiringPiSetup() <0) return 1;
    if((fd=serialOpen("/dev/ttyAMA0",baudrate))<0) return 1;
    printf("Serial communication opened \n");
    fflush(stdout);
    
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == 0) 
    { 
        printf("\n Socket creation error \n"); 
        return -1; 
    } 
    
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR , &opt, sizeof(opt)))
    {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    memset(&serv_addr, '0', sizeof(serv_addr));
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(1881);
    
    int addrlen = sizeof(struct sockaddr_in);
    
    if (bind(sock, (struct sockaddr *)&serv_addr, addrlen)<0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    if (listen(sock, 1) <0)
    {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    printf("1\n");
    addrlen=sizeof(struct sockaddr_in);
    socklen_t sin_size=sizeof(struct sockaddr_in);
    if ((new_socket = accept(sock, (struct sockaddr *)&client, &sin_size)) < 0) 
    { 
        perror("accept"); 
        exit(EXIT_FAILURE); 
    }
    char *client_ip = inet_ntoa(client.sin_addr);
    printf("Accepted new connection from a client %s:%d\n", client_ip, ntohs(client.sin_port));
    
    printf("1\n");
    return 0;
}


PI_THREAD(socketRead){
    

    int valread;
    char buffer[4096]={0}; 

    printf("hola %i\n",new_socket);
    //Nos mantenemos a la escucha
    for(;;){
        //memset(buffer,0,sizeof(buffer));
        //valread = recv( new_socket, buffer, 1024,0);
        while((valread = read(new_socket,buffer,sizeof(buffer)-1))>0){
        /*if ( valread < 0 ) {
            printf ( "An error occured during the receive procedure \n" ) ;
            return 0 ;
        }*/
        buffer[valread]=0;  
        printf("buffer %s\n",buffer);
        write(fd,buffer,strlen(buffer));
        }
    } 
    
}

PI_THREAD(uartRead){
    

    int valread;
    char buffer[4096]={0}; 

    
    //Nos mantenemos a la escucha
    for(;;){
        //memset(buffer,0,sizeof(buffer));
        valread = read( fd, buffer, sizeof(buffer));
        //valread = read(new_socket,buffer,4096);
        //send( new_socket, buffer,4096,0);
        write(new_socket,buffer,sizeof(buffer));
        printf("recibido\n");
    } 
    
}


int main(){
    
    setup();
    printf("adios %i\n",new_socket);
    /* Thread creation */
    piThreadCreate (socketRead);
    piThreadCreate (uartRead);
    for(;;){}
    
    return 0;
}

我没有发现这两个程序之间的差异,所以我的问题是 Python 和 C 库之间是否有任何差异。使用 Python,我可以看到读取消息,但在 C 中,我只收到 0x10 和 0x11。那么,库之间有什么区别还是我的 C 脚本有什么不同?

【问题讨论】:

  • Python 使用相同的系统提供 C 调用。它是一个瘦包装器,它们实际上是相同的。我毫不怀疑代码中存在错误,可能与“一般”在 C 和 Python 之间进行移植有关。
  • 嗯是不是也是一样的读取功能?因为在两个脚本中具有相同的参数并且遵循相同的结构我不明白..
  • 它在操作系统级别的工作方式相同,是的。用于桥接语言/绑定的薄包装器。努力创建一个最小的失败差异案例。
  • 数据真的是ASCII字符串吗?!
  • @AnttiHaapala 这就是我的想法,所有数据都来自 MQTT paho 库。但是,如果它在 Python 中工作,在 C 中是否重要?

标签: python c sockets


【解决方案1】:
PI_THREAD(uartRead){
    ...
    char buffer[4096]={0};
    ... 
        valread = read( fd, buffer, sizeof(buffer));
        ...
        write(new_socket,buffer,sizeof(buffer));

在此代码中,您从串行线路读取 valread 字节,但您始终是 write 4096 字节 (sizeof(buffer))。这意味着您不仅要发送来自串行线路的数据,还要发送buffer 中的大量垃圾数据。

因此问题不在于 Python 和 C 中的套接字之间的区别,而只是 C 程序中的一个错误。

【讨论】:

  • 非常感谢!我在另一个线程中遇到了同样的问题。我花了很多时间试图找到错误。谢谢!
猜你喜欢
  • 1970-01-01
  • 2016-08-15
  • 2017-10-09
  • 1970-01-01
  • 2013-05-21
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多