【发布时间】: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 中是否重要?