udpsocket-C编程绑定和广播
下面是我从公司继承的代码(我不知道是谁写的),这段代码目前适用于我的特定场景,即: 设备(信号发生器)向我发送UDP数据,我需要接收它们,分析它们,有时向设备发送命令(基于分析)。下面是它的外观:udpsocket-C编程绑定和广播,c,sockets,bind,C,Sockets,Bind,下面是我从公司继承的代码(我不知道是谁写的),这段代码目前适用于我的特定场景,即: 设备(信号发生器)向我发送UDP数据,我需要接收它们,分析它们,有时向设备发送命令(基于分析)。下面是它的外观: /********************************************* ** Communication Struct. **********************************************/ typedef struct Ct
/*********************************************
** Communication Struct.
**********************************************/
typedef struct CtxCom
{
int socket_client; //socket
char* cmd; //command
char* recepbuff; //recepbuff
struct sockaddr_in addr_client; //contains IP and PORT
}CtxCom;
extern struct CtxCom init_Ctx_com ( char* IP_client, const int PORT_client, struct timeval timeout )
{
CtxCom ClientCom; //define struct
ClientCom.socket_client = socket(AF_INET, SOCK_DGRAM, 0); //Create the socket
if(ClientCom.socket_client < 0) //Check the creation of the socket
{
perror("[Init_Com] socket()");
exit(errno);
}
struct sockaddr_in addr_me = { 0 }; //create the server struct
addr_me.sin_addr.s_addr = htonl(INADDR_ANY); //any incoming IP
addr_me.sin_port = htons(PORT_client);
addr_me.sin_family = AF_INET; //address family
if(bind(ClientCom.socket_client,(struct sockaddr *) &addr_me, sizeof(addr_me)) < 0) //bind the socket
{
perror("[Init_Com] bind()");
exit(errno);
}
//conf equipment side
ClientCom.addr_client.sin_addr.s_addr = inet_addr(IP_client);
ClientCom.addr_client.sin_port = htons(PORT_client);
ClientCom.addr_client.sin_family = AF_INET;
//timeout
//setsockopt(ClientCom.socket_client , SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout , sizeof (struct timeval));
//fcntl(ClientCom.socket_client, F_SETFL, O_NONBLOCK); //set socket to non block
//Printf info
printf("[Init CtxCom]");
printf(" Socket connected and Client[%s:%d] configured *************** \n",
inet_ntoa(ClientCom.addr_client.sin_addr),
ntohs(ClientCom.addr_client.sin_port) );
return ClientCom;
}
/*Write char* cmd of size cmdSize in the socket specified*/
extern void write_client(struct CtxCom CtxCom, char* cmd, int cmdSize)
{
//adding 0x0a 0x0d to the end of a CMD
cmdSize+=2;
cmd[cmdSize-2]='\r';
cmd[cmdSize-1]='\n';
//send CMD
if(sendto(CtxCom.socket_client, cmd, cmdSize, 0, (struct sockaddr *)&(CtxCom.addr_client), sizeof(CtxCom.addr_client)) < 0)
{
perror("[Write_client] send()");
exit(errno);
}
else
{
//printf( "\n***************SEND OK [%s:%d]******************\n"
// ,inet_ntoa(CtxCom.addr_client.sin_addr), ntohs(CtxCom.addr_client.sin_port) );
}
}
* Give in output the char* strings outStringLLRX with a size of sizeOutStringLLRX*/
extern void read_client(
/*input*/ struct CtxCom CtxCom, struct timeval timeout,
/*output*/ char** outStringLLRX, int* sizeOutStringLLRX)
{
//timeout forced
//timeout.tv_usec=TIMEOUT_LISTEN_GIII;
//Define variables
fd_set readfs;
int loop=1;
int i=0, k=0, z=0, z_prev=0;
int res;
char buf[25500];
int sizeBuf;
//Init variables
memset(buf, '\0' ,sizeof(buf));
for(i=0;i<NB_CHANNELS_LLRX;i++)
{
sizeOutStringLLRX[i]=0;
outStringLLRX[i][0]='\0';
}
//Make sure buffer is empty
memset(buf, '\0' ,sizeof(buf)); //empty recep buffer
FD_ZERO(&readfs); //zero testing
FD_SET(CtxCom.socket_client, &readfs); // set testing
//block until input becomes available
res=select(CtxCom.socket_client+1, &readfs, NULL, NULL, &timeout);
switch (res)
{
case 0: //timeout
printf("TIMEOUT error [Read Client] - No data received \n");
break;
case -1: //error
printf("Error [Read Client] \n");
break;
default : //streams event
if( FD_ISSET(CtxCom.socket_client, &readfs) )
{
sizeBuf=recvfrom (CtxCom.socket_client, buf , 25500, 0, NULL, NULL); //already now wich IP, no need to update
if ( sizeBuf<0 ) //if <0 => no data => error
{
printf("[Read_Client] Read failed : SizeBuf<0 \n");
}
else
{
printf("[Read_Client] Got a buffer of size %d (round %d) \n", sizeBuf, k);
(sizeOutStringLLRX[0])+=sizeBuf;
for( z=0; z<sizeBuf; z++) {outStringLLRX[0][z_prev]=buf[z]; z_prev++;}
}
}
break;
}//switch
//printf("[Read_Client] final size =%d\n", z_prev);
/*printf("***************RECV OK [%s:%d]******************\n",
inet_ntoa(CtxCom.addr_client.sin_addr),ntohs(CtxCom.addr_client.sin_port) );*/
}
/*********************************************
**通信结构。
**********************************************/
类型定义结构CtxCom
{
int socket_client;//socket
char*cmd;//命令
char*recepbuff;//recepbuff
addr_client中的struct sockaddr_;//包含IP和端口
}CtxCom;
外部结构CtxCom init_Ctx_com(char*IP_客户端,const int PORT_客户端,结构timeval超时)
{
CtxCom ClientCom;//定义结构
ClientCom.socket_client=socket(AF_INET,SOCK_DGRAM,0);//创建套接字
if(ClientCom.socket\u client<0)//检查套接字的创建
{
perror(“[Init_Com]socket()”);
出口(errno);
}
struct sockaddr\u in addr\u me={0};//创建服务器结构
addr\u me.sin\u addr.s\u addr=htonl(INADDR\u ANY);//任何传入IP
addr_me.sin_port=htons(客户端端口);
addr\u me.sin\u family=AF\u INET;//地址族
if(bind(ClientCom.socket\u client,(struct sockaddr*)&addr\u me,sizeof(addr\u me))<0)//绑定套接字
{
perror(“[Init_Com]bind()”);
出口(errno);
}
//配置设备端
ClientCom.addr_client.sin_addr.s_addr=inet_addr(IP_client);
ClientCom.addr\u client.sin\u port=htons(port\u client);
ClientCom.addr\u client.sin\u family=AF\u INET;
//超时
//setsockopt(ClientCom.socket_client,SOL_socket,SO_RCVTIMEO,(const char*)和timeout,sizeof(struct timeval));
//fcntl(ClientCom.socket_client,F_SETFL,O_NONBLOCK);//将套接字设置为非块
//打印信息
printf(“[Init CtxCom]”);
printf(“已连接套接字且客户端[%s:%d]已配置***************\n”,
inet_ntoa(ClientCom.addr_client.sin_addr),
ntohs(ClientCom.addr_client.sin_port));
returnclientcom;
}
/*在指定的套接字中写入大小为cmdSize的char*cmd*/
extern void write_客户端(struct CtxCom CtxCom,char*cmd,int cmdSize)
{
//将0x0a 0x0d添加到CMD的末尾
cmdSize+=2;
cmd[cmdSize-2]='\r';
cmd[cmdSize-1]='\n';
//发送命令
如果(发送到(CtxCom.socket\u客户端,cmd,cmdSize,0,(struct sockaddr*)和(CtxCom.addr\u客户端),sizeof(CtxCom.addr\u客户端))<0)
{
perror(“[Write_client]send()”;
出口(errno);
}
其他的
{
//printf(“\n***************发送确定[%s:%d]************************\n”
//,inet_ntoa(CtxCom.addr_client.sin_addr),ntohs(CtxCom.addr_client.sin_port));
}
}
*在输出中给出大小为SizeOutStringLrx的字符*字符串*/
外部无效读取客户端(
/*输入*/struct CtxCom CtxCom,struct timeval超时,
/*输出*/char**outStringLLRX,int*sizeOutstringlrx)
{
//强制超时
//timeout.tv\u usec=timeout\u LISTEN\u GIII;
//定义变量
fd_集readfs;
int循环=1;
int i=0,k=0,z=0,z_prev=0;
国际关系;
char-buf[25500];
int sizeBuf;
//初始变量
memset(buf,'\0',sizeof(buf));
对于(i=0;i您不必担心在套接字上接收广播数据包。假设Linux,man 7 ip
告诉我们“只有在设置了SO_广播套接字标志时才能发送或接收广播地址的数据报”(该标志可以用setsockopt设置,并记录在man 7套接字
中)
bind()
用于选择要侦听的端口,但也用于选择哪个网络接口。该接口由其本地地址指定,INADDR\u ANY
在这种情况下意味着侦听所有网络接口(请参见man 7 ip
)。套接字将从所选接口上的任何(有效)ip地址接收数据.好的,如果没有这个广播标志,就不可能在套接字上看到广播流量?Bind正在创建一种端点,但在本地计算机上?使用INADDR\u ANY,它会自动选择本地计算机上可用的本地IP?我的理解正确吗?谢谢