使用双网卡进行UDP通信
此实验使用一台有两个网卡的PC机和另外两台机进行UDP通信(一台为PC机,一台为ARM板)。
各个函数的使用《Linux下的Socket通信》中已经介绍,这里说明其它几点内容:
要想接收数据,必须创建套接口并绑定到本机地址,ARM板上比较奇怪随便给个地址都可以。
使用双网卡时可以只建一个套接口,绑定地址时使用INADDR_ANY,这样两个网卡的数据都能收到。也可以建两个套接口分别绑到两个IP上,这样就可以通过指定套接口的方式来指定使用哪个IP来发送或接收。
下面是运行于双网卡PC机上的程序,另外两台机的程序只需要把套接口、本机地址、接收线程由两个改为一个即可。
#include
#include
#include
#include
#include
#include
#include
#define PORT 2007
int sockfd, sockfd9;
struct sockaddr_in address0, address9;
int addr_len0, addr_len9;
void *
receive() //用于从跟sockfd绑定的地址接收,
即192.168.0.111
{
int i;
int len;
char buffer[256];
while(1)
{
bzero(buffer, sizeof(buffer));
len = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr
*)&address0, &addr_len0);
printf("eth0 connect to %s\n",inet_ntoa(address0.sin_addr));
printf("receive: %d chars\a\n",len);
for(i=0; i
printf("%c",buffer[i]);
printf("\n");
}
}
void * receive9() //用于从跟sockfd9绑定的地址接收,
即192.168.0.222
{
int i;
int len;
char buffer[256];
while(1)
{
bzero(buffer, sizeof(buffer));
len = recvfrom(sockfd9, buffer, sizeof(buffer), 0, (struct sockaddr
*)&address9, &addr_len9);
printf("eth1 connect to %s\n",inet_ntoa(address9.sin_addr));
printf("receive: %d chars\a\n",len);
for(i=0; i
printf("%c",buffer[i]);
printf("\n");
}
}
int main()
{
int i;
int n;
int addr_len1,
addr_len2;
int len;
struct sockaddr_in
address1, address2;
char buffer[256];
char target_ip[30];
char data[128];
pthread_t
receive_thread; //用于接收数据
pthread_t receive_thread9;
sockfd = socket(AF_INET,
SOCK_DGRAM, 0);
if(sockfd == -1)
{
perror("socket error");
exit(1);
}
sockfd9 = socket(AF_INET,
SOCK_DGRAM, 0);
if(sockfd9 == -1)
{
perror("socket error");
exit(1);
}
address0.sin_family =
AF_INET; //本机地址1
address0.sin_addr.s_addr =
htonl(INADDR_ANY);
address0.sin_addr.s_addr =
inet_addr("192.168.0.111");
address0.sin_port =
htons(PORT);
addr_len0 =
sizeof(address1);
address9.sin_family =
AF_INET; //本机地址2
address9.sin_addr.s_addr =
htonl(INADDR_ANY);
address9.sin_addr.s_addr =
inet_addr("192.168.0.222");
address9.sin_port =
htons(PORT);
addr_len9 =
sizeof(address9);
address1.sin_family =
AF_INET; //目标机1地址
address1.sin_addr.s_addr =
inet_addr("192.168.0.1");
address1.sin_port =
htons(PORT);
addr_len1 =
sizeof(address1);
address2.sin_family =
AF_INET; //目标机2地址
address2.sin_addr.s_addr =
inet_addr("192.168.0.2");
address2.sin_port =
htons(PORT);
addr_len2 =
sizeof(address2);
//要想通过sockfd接收数据,必须绑定到本地地址
if(bind(sockfd, (struct
sockaddr *)&address0, addr_len0) ==
-1) //sockfd用于接收192.168.0.111收到的数据
{
perror("bind error");
exit(1);
}
if(bind(sockfd9, (struct
sockaddr *)&address9, addr_len9) == -1) //sockfd9用于接收192.168.0.222收到的数据
{
perror("bind error");
exit(1);
}
//创建两个线程分别接收两个网卡收到的数据
pthread_create(&receive_thread, NULL, receive, NULL);
pthread_create(&receive_thread9, NULL, receive9, NULL);
while(1)
{
printf("udp>");
bzero(buffer,
sizeof(buffer)); //清缓存
bzero(target_ip,
sizeof(target_ip)); //
bzero(data,
sizeof(data)); //
fgets(buffer,
256, stdin); //输入命令,
格式为:目标地址IP
要发送的字符串(字符串中不能有空格)
sscanf(buffer,
"%s %s", target_ip, data); //解析命令
if(strncmp(target_ip,
"192.168.0.1", 11) == 0)//发往目标地址1
{
printf("send
to %s\n",inet_ntoa(address1.sin_addr));
sendto(sockfd9,
data, strlen(data), 0, (struct sockaddr *)&address1,
addr_len1);
//上面指定sockfd9,则通过本机地址2发送,要想通过本机地址1发送,只须把它改为sockfd.
}
else
if(strncmp(target_ip, "192.168.0.2", 11) == 0)
{
printf("send
to %s\n",inet_ntoa(address2.sin_addr));
sendto(sockfd,
data, strlen(data), 0, (struct sockaddr *)&address2,
addr_len2);
}
}
}