业务场景是主控机A和数据卡B通过UDP通信。因为软件测试,迫于环境须要本地过程间通信。间接将原先跑在两台设施的软件跑在同一台机器,置单方IP都为127.0.0.1。原先主控机和数据卡的接管端口都为6002,现同一台设施运行,两个过程端口不能够雷同。将主控机的接管端口改为6003,即可失常通信。代码如下
UDP初始化库
/*-----------------------------------------------------------**** 文件名: UDP_Driver.c**** 形容: 定义了通过UDP进行通信所需的所有函数和变量**** 定义的函数:** UDP_Init()** UDP_Send()** UDP_Recv()**** 设计注记:********-----------------------------------------------------------*//*UDP运行环境*/#ifdef _WIN32#define UDP_UNDER_VXWORKS 0#else#define UDP_UNDER_VXWORKS 2 /*Windows C++运行环境下定义为0, vxWorks5.x环境下定义为1, vxWorks6.x环境下定义为2*/#endif#if UDP_UNDER_VXWORKS > 0//#include <sysIO.h>#include <netinet/in.h>#include <sockLib.h>#include <string.h>#include <stdio.h>#include <fcntl.h>#include "errnoLib.h"#include "UDP_Driver.h"#if UDP_UNDER_VXWORKS == 2#ifndef SOCKADDR //typedef struct sockaddr SOCKADD#endif#endiftypedef unsigned int SOCKET;#else#include <WinSock2.h>#include <stdio.h>#pragma comment(lib, "WS2_32.lib")#include "UDP_Driver.h"typedef char* caddr_t;static WSADATA wsaData;#endiftypedef struct sockaddr_in SockAddr_TYPE;typedef struct{ int (*Send)(void * const Handler, void * const Payload, int const LenBytes); int (*Recv)(void * const Handler, void * const Buffer, int const MaxBytes); SOCKET Recv_Socket;/*接管和发送的socket*/ SockAddr_TYPE Self_Recv_Address;/*配置接管IP与端口号,用于创立Recv_Socket*/ SockAddr_TYPE Peer_Send_Address;/*配置源端IP与端口号,用于断定接收数据起源*/ SockAddr_TYPE Peer_Recv_Address;/*配置目标IP与端口号,用于指定发送地址*/} UDP_INNER_TYPE;/*.BH-------------------------------------------------------------**** 函数名: UDP_Send**** 形容: UDP发送函数**** 输出参数:** Handler : void * const, UDP句柄** Payload : void * const, 发送数据指针** LenBytes: int const, 发送数据长度**** 输入参数:** 返回值: int, > 0, 发送胜利(返回发送数据长度, 单位:BYTE)** -1, 句柄有效** -2, Payload为空或LenBytes小于1** -3, Socket故障**** 设计注记:****.EH-------------------------------------------------------------*/int UDP_Send(void * const Handler, void * const Payload, int const LenBytes){ UDP_INNER_TYPE * pUDP = (UDP_INNER_TYPE*)Handler; int ret_val = 0; if (pUDP == NULL) ret_val = -1; else if ((Payload == NULL) || (LenBytes < 1)) ret_val = -2; else { ret_val = sendto(pUDP->Recv_Socket/*pUDP->Send_Socket*/, (caddr_t)Payload, LenBytes, 0, (SOCKADDR*)&pUDP->Peer_Recv_Address, sizeof(SockAddr_TYPE));#if UDP_UNDER_VXWORKS > 0 if (ret_val == ERROR)#else if (ret_val == SOCKET_ERROR)#endif { //printf(" UDP_Send Error %s\n", strerror(errno)); //printf("UDP_Send errno = %d\n", WSAGetLastError()); ret_val = -3; } } return ret_val;}/* END of UDP_Send *//*.BH-------------------------------------------------------------**** 函数名: UDP_Recv**** 形容: UDP接管函数**** 输出参数:** Handler : void * const, UDP句柄** Buffer : void * const, 寄存接收数据的缓存指针** MaxBytes: int const, Buffer的最大容量**** 输入参数:** 返回值: int, >= 1, 理论获取到的数据长度(单位:BYTE)** 0, 无数据可接管** -1, 句柄有效** -2, Buffer为空或MaxBytes长度有余** -3, Socket故障**** 设计注记:****.EH-------------------------------------------------------------*/int UDP_Recv(void * const Handler, void * const Buffer, int const MaxBytes){ UDP_INNER_TYPE * pUDP = (UDP_INNER_TYPE*)Handler; SockAddr_TYPE Source_Address; int Source_AddrSize = sizeof(SockAddr_TYPE); int ret_val = 0; if (pUDP == NULL) ret_val = -1; else if ((Buffer == NULL) || (MaxBytes < 1)) ret_val = -2; else { while ((ret_val = recvfrom(pUDP->Recv_Socket, (char*)Buffer, MaxBytes, 0, (SOCKADDR*)&Source_Address, &Source_AddrSize)) > 0) { if ((0xC00A0050 == pUDP->Peer_Send_Address.sin_addr.s_addr) /*&& (Source_Address.sin_port == pUDP->Peer_Send_Address.sin_port)*/) { // just for test()MMP Send Data, data monitor in wireshark, but IDMP have no data recived! } /*对端往用XXXX发数据,本端就往对端的这个端口XXXX发数据(默认认为对端收发接口统一)*/ if ((Source_Address.sin_addr.s_addr == pUDP->Peer_Send_Address.sin_addr.s_addr) /*&& (Source_Address.sin_port == pUDP->Peer_Send_Address.sin_port)*/) { //printf("[UDP_Recv] recv port %d, %d\n", htons(Source_Address.sin_port), htons(pUDP->Self_Recv_Address.sin_port)); pUDP->Peer_Recv_Address.sin_port = Source_Address.sin_port; break; } }#if 0 ret_val = recvfrom(pUDP->Recv_Socket, (char*)Buffer, MaxBytes, 0, (SOCKADDR*)&Source_Address, &Source_AddrSize); if(ret_val > 0){ if ((Source_Address.sin_addr.s_addr == pUDP->Peer_Send_Address.sin_addr.s_addr) /*&& (Source_Address.sin_port == pUDP->Peer_Send_Address.sin_port)*/) { pUDP->Peer_Recv_Address.sin_port = Source_Address.sin_port; } }#endif if (ret_val < 0){ ret_val = -3; } } return ret_val;}/* END of UDP_Recv *//*.BH-------------------------------------------------------------** ** 函数名: UDP_Init**** 形容: UDP初始化接口函数**** 输出参数:** Handler : UDP_STRUCT_TYPE * const, 需初始化的UDP句柄** Peer_IP : unsigned int const, 对方设施IP地址** Peer_Send_Port : unsigned short const, 对方设施发送UDP端口号** Peer_Recv_Port : unsigned short const, 对方设施接管UDP端口号** Self_IP : unsigned int const, 本方设施IP地址(单网卡环境可置零,多网卡环境必须指定通信网卡地址)** Self_Send_Port : unsigned short const, 本方设施发送UDP端口号** Self_Recv_Port : unsigned short const, 本方设施接管UDP端口号** Recv_Cache : int const, 接管缓存大小(零碎默认为8192, 大数据量时可减少)** Recv_Block_Mode: int const, 接管模式: 0-阻塞, 1-非阻塞**** 输入参数:** 返回值: int, >= 0, 初始化胜利** -1, 初始化失败(句柄有效)**** 设计注记:****.EH-------------------------------------------------------------*/int UDP_Init(UDP_STRUCT_TYPE * const Handler, unsigned int const Peer_IP, unsigned short const Peer_Send_Port, unsigned short const Peer_Recv_Port, unsigned int const Self_IP, unsigned short const Self_Send_Port, unsigned short const Self_Recv_Port, int const Recv_Cache, int const Recv_Block_Mode){ UDP_INNER_TYPE *pUDP = (UDP_INNER_TYPE*)Handler; unsigned int Recv_Mode; int Ret;#if UDP_UNDER_VXWORKS == 0 static int First_Init = 1; if (First_Init) WSAStartup(MAKEWORD(2, 2), &wsaData); First_Init = 0;#endif if (pUDP == NULL) return -1; /*send buffer默认100000*/ // if(0 == getsockopt(pUDP->Send_Socket, SOL_SOCKET, SO_SNDBUF, buffer, &Send_Cache)) // printf("udp send buff size %d\n", *(int*)buffer); pUDP->Self_Recv_Address.sin_family = AF_INET; pUDP->Self_Recv_Address.sin_addr.s_addr = htonl(Self_IP); pUDP->Self_Recv_Address.sin_port = htons(Self_Recv_Port); pUDP->Recv_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); Ret = bind(pUDP->Recv_Socket, (SOCKADDR*)&(pUDP->Self_Recv_Address), sizeof(SockAddr_TYPE)); if (Ret < 0) { printf("Bind Failed, Ret-%d, sock-%d\n", Ret, pUDP->Recv_Socket); return -2; } if (Recv_Cache > 8192){ setsockopt(pUDP->Recv_Socket, SOL_SOCKET, SO_RCVBUF, (char*)&Recv_Cache, sizeof(int)); setsockopt(pUDP->Recv_Socket, SOL_SOCKET, SO_SNDBUF, (char*)&Recv_Cache, sizeof(int)); } Recv_Mode = (Recv_Block_Mode > 0);#if UDP_UNDER_VXWORKS > 0 ioctl(pUDP->Recv_Socket, FIONBIO, &Recv_Mode);#else ioctlsocket(pUDP->Recv_Socket, FIONBIO, (u_long*)&Recv_Mode);#endif pUDP->Peer_Send_Address.sin_family = AF_INET; pUDP->Peer_Send_Address.sin_addr.s_addr = htonl(Peer_IP); pUDP->Peer_Send_Address.sin_port = htons(Peer_Send_Port); pUDP->Peer_Recv_Address.sin_family = AF_INET; pUDP->Peer_Recv_Address.sin_addr.s_addr = htonl(Peer_IP); pUDP->Peer_Recv_Address.sin_port = htons(Peer_Recv_Port); pUDP->Send = UDP_Send; pUDP->Recv = UDP_Recv; return 0;}/* END of UDP_Init */#undef SockAddr_TYPE#if UDP_UNDER_VXWORKS > 0 #undef SOCKADDR #undef SOCKET#else #undef caddr_t#endif#undef UDP_UNDER_VXWORKS
主控机初始化(A):
#define DLR_CARD_IP 0x7F000001/*0xAC100A0F*/#define DLR_RECV_IDMP_PORT 6002#define IDMP_RECV_DLR_PORT 6003/*6002*//*BASEIO_UDP0_CHANNEL_DLR:服务器端(DLR)IP地址:172.16.10.15*/Ret = UDP_Init(&UDP_Handler[0], DLR_CARD_IP, DLR_RECV_IDMP_PORT, DLR_RECV_IDMP_PORT, IDMP_SIM_IP1, 0, IDMP_RECV_DLR_PORT, 64 * 1024, UDP_RECV_NONBLK);if (Ret != 0) { IOM_Report_Fault(Chn++, CDMP_FAIL); USR_LOG(LOGER_IOSS, LOG4C_PRIORITY_ERROR, "%s, %d UDP_Init Error %d\n", "DLR", 0, Ret);}else { IOM_Report_Fault(Chn++, CDMP_PASS);}
数据卡端初始化(B):
#define UdpLocalIP 0x7F000001#define DLR_RECV_IDMP_PORT 6002#define IDMP_RECV_DLR_PORT 6003/*6002*/Ret = UDP_Init(&UDP_Handler[BASEIO_UDP0_CHANNEL_DLR], UdpLocalIP/*0xAC100A10*/, IDMP_RECV_DLR_PORT, IDMP_RECV_DLR_PORT, UdpLocalIP, DLR_RECV_IDMP_PORT, DLR_RECV_IDMP_PORT, 64 * 1024, UDP_RECV_NONBLK);if (Ret != 0) { //IOM_Report_Fault(Chn++, CDMP_FAIL); USR_LOG(LOGER_IOSS, LOG4C_PRIORITY_ERROR, "MCU UDP_Init Error %d\n", Ret);}
这样,一个点对点的本地过程间UDP通信模型就建设实现了。
不论是A发B还是B发A,都能够失常通信。如果谋求效率能够将SOCKET绑定为AF_UNIX,通过文件进行过程间数据收发。