Linux平台Socket基础应用-UDP通信程序
一、实验目的和任务
- 本实验要求复习ubuntu的IP配置知识。
- 了解的掌握使用socket编程的基本方法。
二、实验设备介绍
1.软件需求: win7操作系统,VMware workstation,ubuntu12 [配置交叉编译环境]。
2.硬件需求: PC内存大于1G,硬盘空间大于20G;smart210开发板。
三、注意事项和要求
1.启动虚拟机前应首先使用"虚拟网络编辑器"配置要桥接的网卡。
2.检查网线是否连接正常。
3.调试程序时需要两个程序同时运行进行联调。
四、实验内容和步骤
4.0 PC通过网线连接开发板
实验室PC主机(Win7)具有两个网卡,其网络初始配置如下。
PC机连接开发板可以用串口线还可以使用网线,网线连接比较稳定,数据传输速度快。参照下面的示意图插入网线,这条网线也是称为交叉线,能够实现直接用网卡连接两台电脑,仅使用网线与开发板连接,此时PC机、开发板与虚拟机实现物理连通。
在开发板的终端窗口使用ifconfig命令查看开发板的初始IP,其地址是192.168.1.230
设置PC的win7系统连接开发板的网卡IP为 192.168.1.99,无需设置网关,在win7主机命令窗口中使用ping命令可以测试开发板与win7联通性。
虚拟机中的ubuntu也可以与开发板网络通信,首先要设置虚拟的桥接网卡,在虚拟网络编辑器中选择用交叉线与开发连接的网卡,如下图,再启动虚拟机进入ubuntu系统。
设置虚拟机ubuntu的IP地址,无需设网关,这时开发板与ubuntu已经实现网络联通了,使用ping命令测试连通性。
telnet和ssh协议都可实现远程网络登陆主机,win7主机中XShell软件支持采用SSH协议连接开发板,开发板默认已经启动了ssh服务。在XShell软件中新建一个连接,协议选择SSH,目标地址为192.168.1.230,即开发板的IP地址。
使用的登陆账号为root,根据用户手册,其登陆密码是fa。
输入密码:fa 连接成功。
在UBUNTU中使用ssh命令登录开发板,开发板的IP地址是 192.168.1.230,则输入命令
ssh root@192.168.1.230,然后输入密码fa即可进入开发板的字符终端。
4.1简单的UDP服务端与客户端通讯
UDP通讯模式如下图所示,只要实现绑定操作的socket资源就可以执行接收任务。UDP没有连接的概念,也没有断开连接的需要,直接调用sendto方法即可实现信息发送,接收端使用receivefrom方法接收数据。UDP通讯中使用的方法是socket,bind,sendto,receivefrom,close。UDP是常用的无连接的网络协议,SNMP网络管理的协议就是基于UDP的应用层协议。
4.2发送端代码uecho_client.c
uDP数据发送端,程序从键盘接收字符输入,再通过UDP方法发送到目标机器。
//023.c udp数据发送端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>//close方法
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 30
void error_handling(char * message);
int main(int argc,char *argv[])
{
int sock;
char message[BUF_SIZE];
int str_len;
socklen_t adr_sz;
struct sockaddr_in serv_adr,from_adr;
//命令 IP PORT
if(argc!=3)
{
printf("Usage :%s <IP> <PORT>\n",argv[0]);
exit(1);
}
sock=socket(PF_INET,SOCK_DGRAM,0);
if(sock==-1)
error_handling("UDP socket() create failed.");
memset(&serv_adr,0,sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
//IP地址
serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
//PORT
serv_adr.sin_port=htons(atoi(argv[2]));
while(1)
{
fputs("Insert message(q to quit):",stdout);
memset(message,0, BUF_SIZE);
fgets(message,sizeof(message),stdin);
if(!strcmp(message,"q\n")||!strcmp(message,"Q\n"))
break;
sendto(sock,message,strlen(message),0,
(struct sockaddr*)&serv_adr,sizeof(serv_adr));
adr_sz=sizeof(from_adr);
str_len=recvfrom(sock,message,BUF_SIZE,0,
(struct sockaddr*)&from_adr,&adr_sz);
message[str_len]=0;
printf("Message from server: %s",message);
}
close(sock);
return 0;
}
//错误处理是将信息输出到标准输出,然后退出进程。
void error_handling(char * message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
4.3接收端代码uecho_server.c
本小节示例代码的UDP服务端是接收发送端的数据,并直接原样sendto返还,该程序将无法退出。
//024.c udp数据接收,并进行回显
//头文件与uecho_ client.c一样
int main(int argc,char *argv[])
{
int serv_sock;
char message[BUF_SIZE];
int str_len;
socklen_t clnt_adr_sz;
struct sockaddr_in serv_adr,clnt_adr;
//命令 PORT
if(argc!=2)
{
printf("Usage :%s <PORT>\n",argv[0]);
exit(1);
}
serv_sock=socket(PF_INET,SOCK_DGRAM,0);
if(serv_sock==-1)
error_handling("UDP socket() create failed.");
memset(&serv_adr,0,sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
//IP地址
serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
//PORT
serv_adr.sin_port=htons(atoi(argv[1]));
if(bind(serv_sock,(struct sockaddr *)&serv_adr,sizeof(serv_adr))==-1)
error_handling("UDP bind() failed.");
while(1)
{
clnt_adr_sz=sizeof(clnt_adr);
str_len=recvfrom(serv_sock,message,BUF_SIZE,0,
(struct sockaddr*)&clnt_adr,&clnt_adr_sz);
printf("%s",message);
memset(message,0, BUF_SIZE);
scanf("%s",message);
sendto(serv_sock,message,str_len,0,
(struct sockaddr*)&clnt_adr,clnt_adr_sz);
}
close(serv_sock);
return 0;
}
使用gcc工具编译程序后运行UDP客户端与服务端的效果如下图,注意服务端程序不会有输出,也不终止。试修改服务端代码使服务端正常结束[非kll]。
下面是使服务端正常结束的截图,客户端输入q字符后,两个进程都结束。