我需要合并客户端和服务器代码。在这方面,我将非常感谢你的帮助。我在组合Python中共享C服务器和客户端代码。错误的葡萄柚可以在底线找到。
C服务器代码
#include <unistd.h>
#include <stdio.h> // standard input / output functions
#include <stdlib.h>
#include <string.h> // string function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#include <time.h>
#include <stdint.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "list.h"
#include "pack.h"
#define SOCK_PATH "../sockets/socketNodeServer"
#define DEBUG_FILE "./debug.txt"
#pragma pack(1)
// Structure definitions
typedef struct serialRx_s{
list* llistScatteredRx;
list* llistOrderedRx;
uint8_t scratchpad[SCRATCHPAD_SIZE];
uint8_t remaining;
uint16_t lostPackets;
uint16_t receivedPackets;
int fd;
}serialRx_t;
typedef struct serialTx_s{
list* llistTx;
uint16_t sentPackets;
int fd;
}serialTx_t;
typedef struct monitor_s{
struct serialRx_s *rx_p;
struct serialTx_s *tx_p;
FILE *fp;
}monitor_t;
#pragma pack()
// Public function prototypes
// Private function prototypes
static void *rxSerial_f(void *arg);
static void *txSerial_f(void *arg);
static void *log_f(void *arg);
static void *monitor_f(void *arg);
static int orderScattered_rxData(struct serialRx_s *rx);
static int fillupScratchpad(struct serialRx_s *rx);
static void freeNode(void *data);
static void *prep_TxGoodies(int fd);
static void *prep_RxGoodies(int fd);
static void *prep_monitoring(struct serialRx_s *rx, struct serialTx_s *tx);
static void set_blocking (int fd, int should_block);
static int set_interface_attribs (int fd, int speed, int parity);
static void *form_node_data_packet(void *buf, int len);
static int setNonBlocking(int fd);
static int set_interface_attribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf ("error %d from tcgetattr", errno);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
// For details about blocking in non canonical (binary mode)
// check out http://www.tldp.org/HOWTO/html_single/Serial-HOWTO/
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
printf ("error %d from tcsetattr", errno);
return -1;
}
return 0;
}
static void set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf ("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
printf ("error %d setting term attributes", errno);
}
static void * prep_monitoring(struct serialRx_s *rx, struct serialTx_s *tx)
{
struct monitor_s *monitor_p = NULL;
monitor_p = (struct monitor_s *)malloc(sizeof(struct monitor_s));
if(NULL == monitor_p){
return NULL;
}
monitor_p->rx_p = rx;
monitor_p->tx_p = tx;
monitor_p->fp = fopen(DEBUG_FILE, "w+");
return monitor_p;
}
static void *prep_RxGoodies(int fd)
{
struct serialRx_s *rx = NULL;
rx = (struct serialRx_s *)malloc(sizeof(struct serialRx_s));
rx->llistScatteredRx = create_list();
rx->llistOrderedRx = create_list();
rx->fd = fd;
memset(rx->scratchpad, 0, sizeof(rx->scratchpad));
rx->remaining = 0;
rx->lostPackets = 0;
rx->receivedPackets = 0;
return rx;
}
static void *prep_TxGoodies(int fd)
{
struct serialTx_s *tx = NULL;
tx = (struct serialTx_s *)malloc(sizeof(struct serialTx_s));
tx->llistTx = create_list();
tx->fd = fd;
tx->sentPackets = 0;
return tx;
}
static void freeNode(void *data)
{
free( (uint8_t *)data);
}
static int fillupScratchpad(struct serialRx_s *rx)
{
int targetNodeIndex = -1;
int nodeLen = 0;
uint8_t *nodeData = NULL;
int offset = 0;
uint8_t *pointer = NULL;
targetNodeIndex = payloadLen_2_index(rx->llistScatteredRx, PACKET_SIZE - rx->remaining);
//printf("targetNodeIndex value %d\n", targetNodeIndex);
for(int i=0; i <= targetNodeIndex ; i++){
offset = rx->remaining;
pointer = (uint8_t *)front(rx->llistScatteredRx); // first byte is for length
nodeLen = pointer[0];
//nodeLen = ((uint8_t *)front(rx->llistScatteredRx))[0]; // first byte is for length
//printf("nodeLen in fillupScratchpad %d\n", nodeLen);
nodeData = (uint8_t *)front(rx->llistScatteredRx) + 1; // first byte is for length
memcpy(rx->scratchpad + offset, nodeData, nodeLen);
rx->remaining += nodeLen;
//for(int j=0; j<rx->remaining; j++)
//{
// printf("scratchpad[%d]: %X\n", j, (rx->scratchpad)[j]);
//}
remove_front(rx->llistScatteredRx, freeNode);
}
return targetNodeIndex;
}
static int orderScattered_rxData(struct serialRx_s *rx)
{
int packetBeginIndex = 0;
struct raw_node_data_s *raw = NULL;
// parse the scratchpad buffer until the last remaining byte
// note that since we have a larger buffer size than what we use
// it's safe to do this.
for(int i=0; i < (rx->remaining) ; i++)
{
// Check whether we have a suitable package
if(rx->scratchpad[i] == START_CODE &&
rx->scratchpad[i+PACKET_SIZE-1] == STOP_CODE)
{
//printf("start & stop matches\n");
raw = (struct raw_node_data_s *)malloc(sizeof(struct raw_node_data_s));
memcpy(raw, rx->scratchpad + i, sizeof(struct raw_node_data_s));
//print_raw_node_data(raw);
push_back(rx->llistOrderedRx, raw);
rx->receivedPackets++;
//TODO: Check for CRC
// clear up memory area between beginning of scratchpad and Stop_Code
memset(rx->scratchpad, 0, i+PACKET_SIZE-1);
// move remaining bytes to the beginning of scratchpad buffer
// no overlapping should occur but still, use memmove instead of memcpy
memmove(rx->scratchpad,
rx->scratchpad + i + PACKET_SIZE, // point to right after the healthy packet
rx->remaining - ( i + PACKET_SIZE)); // get remaining bytes after packet end
// update remaining bytes value
rx->remaining = rx->remaining - (i + PACKET_SIZE);
packetBeginIndex = i; // success
break;
}
}
// if no packets can be formed, check whether we are running out of
// scratchpad buffer, clear up memory if this is the case. Make sure
// to increase packet lost counter
//if( !packetBeginIndex && (rx->remaining >= 2 * PACKET_SIZE) )
if( (rx->remaining >= (3 * PACKET_SIZE)) )
{
printf("we are running out of space\n");
printf("scratchpad size: %d\n", rx->remaining);
for(int i=0; i < (rx->remaining) ; i++)
{
if(rx->scratchpad[i] == START_CODE){
// clear up the first packet area and move up the
// remaining bytes to the beginning of buffer
memset(rx->scratchpad, 0, i-1);
memmove(rx->scratchpad,
rx->scratchpad + i,
rx->remaining - i );
rx->remaining -= i;
rx->lostPackets += 1;
}
}
}
// don't care for START_CODE, clear up an area
// big enough to hold a full packet
if((rx->remaining >= 3 * PACKET_SIZE)){
printf("buffer is a complete mess, clear up stuff\n");
// buffer is a complete mess,
// clear up a whole packet
memset(rx->scratchpad, 0, PACKET_SIZE);
memmove(rx->scratchpad,
rx->scratchpad + PACKET_SIZE+1,
rx->remaining - PACKET_SIZE);
rx->remaining -= PACKET_SIZE;
rx->lostPackets += 1;
}
//for(int j=0; j<rx->remaining; j++)
//{
// printf("scratchpad after cleanup[%d]: %X\n", j, (rx->scratchpad)[j]);
//}
return packetBeginIndex;
}
static void *txSerial_f(void *arg)
{
struct serialTx_s *tx = (struct serialTx_s *)arg;
struct raw_node_data_s *txRaw = NULL;
int n = 0;
//txRaw = prep_transaction_data();
//print_raw_node_data(txRaw);
sleep(1);
while(1)
{
//n = write(tx->fd, txRaw, sizeof(txRaw));
if(size(tx->llistTx)){
txRaw = front(tx->llistTx);
n = write(tx->fd, txRaw, PACKET_SIZE);
//printf("sending %d bytes via serial \n", n);
remove_front(tx->llistTx, freeNode);
tx->sentPackets += 1;
}
sleep(1);
}
return NULL;
}
static void *form_node_data_packet(void *buf, int len)
{
struct raw_node_data_s *raw = NULL;
raw = (struct raw_node_data_s *)malloc(sizeof(struct raw_node_data_s));
if(!raw){
fprintf(stderr,"can't allocate memory for raw node\n");
return NULL;
}
memcpy(raw, buf, len);
//print_raw_node_data(raw);
return raw;
}
//TODO: Move this function to a new source file for socket operations
static int setNonBlocking(int fd)
{
int flags;
/* if O_NONBLOCK is defined, use the fcntl function */
if(-1 == (flags = fcntl(fd, F_GETFL, 0))){
flags = 0;
}
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
static void *monitor_f(void *arg)
{
struct monitor_s *mon = (struct monitor_s *)arg;
struct raw_node_data_s *txRaw = NULL;
uint8_t rxbuf[100];
// socket operation related variables
int fdBind, fdAccept;
int t, len, status;
struct sockaddr_un local;
struct sockaddr_un remote;
if(-1 == (fdBind = socket(AF_UNIX, SOCK_STREAM, 0)))
{
fprintf(stderr, "can't open socket: %s\n", strerror(errno));
return (void *)NULL;
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if( bind(fdBind, (struct sockaddr *)&local, len) == -1){
fprintf(stderr, "can't bind: %s\n", strerror(errno));
return (void *)NULL;
}
if(-1 == listen(fdBind, 5)){ // number of listenes can actually be less
fprintf(stderr, "can't listen: %s\n", strerror(errno));
return (void *)NULL;
}
for(;;){
socklen_t size = sizeof(remote);
int rcvdBytes = 0;
fprintf(stderr, "waiting for a connection\n");
if( -1 == (fdAccept = accept(fdBind, (struct sockaddr *)&remote, &size)) )
{
fprintf(stderr, "can't accept: %s\n", strerror(errno));
return (void *)NULL;
}
//setNonBlocking(fdAccept);
status = 1;
printf("connected\n");
do{
if( (t = recv(fdAccept, rxbuf, 100, 0)) > 0){
fprintf(stderr, "incoming bytes len from server: %d\n", t);
for(int ii=0; ii < t; ii++){
printf("incoming data[%i]:%X\n", ii, rxbuf[ii]);
}
txRaw = (struct raw_node_data_s *)form_node_data_packet(rxbuf, t);
push_back(mon->tx_p->llistTx, txRaw);
}else if(t < 0){
perror("recv"); // if nonblocking then wouldhaveblocked would come here too
}else{
fprintf(stderr, "server closed connection\n");
status = 0;
}
usleep(200);
}while(status);
sleep(2);
close(fdBind);
} // while(1), thread start
return NULL;
}
static void *log_f(void *arg)
{
struct monitor_s *log = (struct monitor_s *)arg;
struct raw_node_data_s *rxRaw = NULL;
while(1)
{
if( size(log->rx_p->llistOrderedRx)){
rxRaw = front(log->rx_p->llistOrderedRx);
printf("log thread\n");
print_raw_node_data(rxRaw);
remove_front(log->rx_p->llistOrderedRx, freeNode);
//fprintf(mon->fp, "\rSent Packets: %d", i);
fprintf(log->fp, "Sent Packets: %d\n", log->tx_p->sentPackets);
fprintf(log->fp, "Received Packets: %d\n", log->rx_p->receivedPackets);
fprintf(log->fp, "Dropped Packets: %d\n", log->rx_p->lostPackets);
fflush(log->fp);
sleep(1);
}
} // while (1)
return NULL;
}
static void *rxSerial_f(void *arg)
{
struct serialRx_s *rx = (struct serialRx_s *)arg;
int n = 0;
uint8_t buf[100] = {0};
uint8_t *dataPack = NULL;
tcflush(rx->fd, TCIFLUSH); /* Discards old data in the rx buffer */
while(1)
{
n = read(rx->fd, (uint8_t *)buf, sizeof(struct raw_node_data_s));
//for(int ii=0; ii < n; ii++){
// printf("incoming serial data[%i]:%X\n", ii, ((uint8_t *)buf)[ii]);
//}
if(n > 0){
//printf("read %d bytes\n", n);
dataPack = (uint8_t *)malloc(sizeof(uint8_t)* n);
dataPack[0] = n;
memcpy(dataPack + 1, buf, sizeof(uint8_t)*n);
push_back(rx->llistScatteredRx, dataPack);
//printf("linked list size after read: %d\n", size(rx->llistScatteredRx));
//for(int i=0; i<n; i++)
//{
// printf("read data[%d]: %X\n", i, dataPack[i+1]);
//}
dataPack = NULL;
memset(buf, 0, sizeof(buf)); // clear up
// Check whether we have enough data in the
// scratchpad to forma packet
fillupScratchpad(rx);
orderScattered_rxData(rx);
}else if(n < 0){
printf("error in read operation\n");
}else{
//printf("no data - rx\n");
}
sleep(1);
} // while(1)
return NULL;
} //void *rxSerial_f(void *arg)
// *************************************************
// *************************************************
// *************************************************
// ************** TODO *************************
// * Have thread functions in seperate files
// * Implement CRC check mechanism
// * Implement DAC switch mechanism
// * Implement for loop on writes to Serial Device
// to make sure that all data is sent on the tx line
int main(void)
{
pthread_t idThreadSerial[2]; // wr, rd
char *portname = "/dev/ttyS2";
struct serialRx_s *serialRx_p = NULL;
struct serialTx_s *serialTx_p = NULL;
struct monitor_s *monitor_p = NULL;
srand(time(NULL)); // generate seed data for random()
printf("size of raw_node_data_s structure: %ld\n", sizeof(struct raw_node_data_s));
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
set_interface_attribs (fd, B38400, 0); // set speed to 38400 bps, 8n1 (no parity)
//set_blocking (fd, 0); // set no blocking
serialTx_p = (struct serialTx_s *)prep_TxGoodies(fd);
serialRx_p = (struct serialRx_s *)prep_RxGoodies(fd);
monitor_p = (struct monitor_s *)prep_monitoring(serialRx_p, serialTx_p);
fwrite ("hello!\n", sizeof(uint8_t), 7, stdout);
sleep(1);
pthread_create(&idThreadSerial[3], NULL, log_f, (void *)monitor_p);
pthread_create(&idThreadSerial[2], NULL, monitor_f, (void *)monitor_p);
//pthread_create(&idThreadSerial[1], NULL, rxSerial_f, (void *)serialRx_p);
//pthread_create(&idThreadSerial[0], NULL, txSerial_f, (void *)serialTx_p);
pthread_join(idThreadSerial[0], NULL);
pthread_join(idThreadSerial[1], NULL);
pthread_join(idThreadSerial[2], NULL);
pthread_join(idThreadSerial[3], NULL);
fwrite("all threads returned, exiting now...\n", sizeof(uint8_t), 40, stdout);
return 0;
}
Python客户端代码
# -*- coding: utf-8 -*-
import socket
import os, os.path
print "Connecting..."
if os.path.exists( "../sockets/socketNodeServer" ):
client = socket.socket( socket.AF_UNIX, socket.SOCK_DGRAM )
client.connect( "../sockets/socketNodeServer" )
print "Ready."
print "Ctrl-C to quit."
print "Sending 'DONE' shuts down the server and quits."
while True:
try:
x = raw_input( "> " )
if "" != x:
print "SEND:", x
client.send( x )
if "DONE" == x:
print "Shutting down."
break
except KeyboardInterrupt, k:
print "Shutting down."
client.close()
else:
print "Couldn't Connect!"
print "Done
&#34;
错误
Connecting...
Traceback (most recent call last):
File "client.py", line 8, in <module>
client.connect( "../sockets/socketNodeServer" )
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 91] Protocol wrong type for socket
答案 0 :(得分:0)
在您的C代码中,您可以创建一个流
fdBind = socket(AF_UNIX, SOCK_STREAM, 0)
并在Python中有一个数据报:
client = socket.socket( socket.AF_UNIX, socket.SOCK_DGRAM )
当然,这是套接字的错误类型。在两边使用相同的STREAM
或DGRAM
。