实验五
实验五 socket
一、实验目的
1.熟悉linux系统,学会简单linux指令
2.熟悉OK6410-A开发板的烧入步骤
3.熟悉ARM寄存器,地址等。
4.了解网络协议,服务器算法等
二、实验仪器
开发机环境
操作系统:ubuntu 20.04
交叉编译环境:arm-linux-gcc 4.6.4
6410板子内核源码:linux-3.0.1
目标板环境
OK6410-A linux-3.0.1
三、实验内容(原理)
完成主机和客户机/服务器之间的连接
四、实验步骤
1.进行桥接网络
1.在虚拟网络编辑器中添加一个桥接网络
2.将网络配置器改为桥接模式
3.将ubuntu内的ip改为192.168.0.x,子网掩码,网关用自己的,DNS为8.8.8.8
2.编写实验程序
详见第五模块
3.烧入单片机
在中断输入以下命令
arm-linux-gcc -o se service.c
gcc client.c -o cl
make
最后生成如下文件
4.编译运行
1.打开终端
2.加载驱动
#insmod /sdcard/driver_led.ko
3.创建设备文件
#mknod /dev/my_led c 240 0
4.测试
./se
5.卸载驱动
#rmmod driver_led
6.打开ubuntu中断
./cl 192.168.0.232
五、实验程序(包括流程图)
1.client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
int main(int argc,char **argv)
{
pid_t fd;
const char buff[] = "Hello! Welcome here gggggggggggg!\r\n";
//定义要发送的数据缓冲区;
int sockfd,connsock; //定义一个socket套接字,用于通讯
struct sockaddr_in serveraddr;//定义网络套接字地址结构
if(argc!= 2)
{
printf("Usage: echo ip地址");
exit(0);
}
sockfd =socket(AF_INET,SOCK_STREAM,0); //创建一个套接字
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family = AF_INET; //指定使用的通讯协议族
serveraddr.sin_port = htons(5000);//指定要连接的服务器的端口
inet_pton(AF_INET, argv[1], &serveraddr.sin_addr);
connect(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); //连接服务器
send(sockfd,buff,sizeof(buff), 0);//向客户端发送数据
close(sockfd); //关闭套接字
return(0);
}
2.driver_led.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h> /* copy_to_user,copy_from_user */
#include <linux/miscdevice.h>
#include <linux/pci.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-m.h>
#include <plat/gpio-cfg.h>
MODULE_LICENSE("GPL" );
#define LED_MAJOR 240
int led_open (struct inode *inode,struct file *filp)
{
unsigned tmp;
tmp = readl(S3C64XX_GPMCON);
tmp = (tmp & ~(0xffff) | (0x1111)); writel(tmp, S3C64XX_GPMCON);
printk("#########open######\n");
return 0;
}
ssize_t led_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
{
printk("#########read######\n");
return count;
}
ssize_t led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
char wbuf[10];
unsigned tmp;
printk("#########write######\n");
copy_from_user(wbuf,buf,count);
switch(wbuf[0])
{
case 0://on1
tmp = readl(S3C64XX_GPMDAT); tmp &= ~(0x1);
writel(tmp, S3C64XX_GPMDAT);
break;
case 1: //off1
tmp = readl(S3C64XX_GPMDAT); tmp |= (0x1);
writel(tmp, S3C64XX_GPMDAT);
break;
case 2: //on2
tmp = readl(S3C64XX_GPMDAT); tmp &= ~(0x2);
writel(tmp, S3C64XX_GPMDAT);
break;
case 3: //off2
tmp = readl(S3C64XX_GPMDAT); tmp |= (0x2);
writel(tmp, S3C64XX_GPMDAT);
break;
case 4: //on3
tmp = readl(S3C64XX_GPMDAT); tmp &= ~(0x4);
writel(tmp, S3C64XX_GPMDAT);
break;
case 5: //off3
tmp = readl(S3C64XX_GPMDAT); tmp |= (0x4);
writel(tmp, S3C64XX_GPMDAT);
break;
case 6: //on4
tmp = readl(S3C64XX_GPMDAT); tmp &= ~(0x8);
writel(tmp, S3C64XX_GPMDAT);
break;
case 7: //off4
tmp = readl(S3C64XX_GPMDAT); tmp |= (0x8);
writel(tmp, S3C64XX_GPMDAT);
break;
case 8: //onall
tmp = readl(S3C64XX_GPMDAT); tmp |= (0xf);
writel(tmp, S3C64XX_GPMDAT);
break;
case 9: //off all
tmp = readl(S3C64XX_GPMDAT);tmp &= (0xf);
writel(tmp, S3C64XX_GPMDAT);
break;
default :
break;
}
return count;
}
int led_release (struct inode *inode, struct file *filp)
{
printk("#########release######\n");
return 0;
}
struct file_operations led_fops ={
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};
int __init led_init (void)
{
int rc;
printk ("Test led dev\n");
rc = register_chrdev(LED_MAJOR,"led",&led_fops);
if (rc <0)
{
printk ("register %s char dev error\n","led");
return -1;
}
printk ("ok!\n");
return 0;
}
void __exit led_exit (void)
{
unregister_chrdev(LED_MAJOR,"led");
printk ("module exit\n");
return ;
}
module_init(led_init);
module_exit(led_exit);
3.service.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
void main()
{
pid_t fd;
int listensock,connsock;
char recvbuff[100]; //定义要接收的数据缓冲区
struct sockaddr_in serveraddr; //定义网络套接字地址结构
listensock = socket(AF_INET,SOCK_STREAM,0);
//创建一个套接字,用于监听
bzero(&serveraddr,sizeof(struct sockaddr)); //地址结构清零
serveraddr.sin_family = AF_INET; //指定使用的通讯协议族
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); //指定接受任何连接
serveraddr.sin_port = htons(5000); //指定监听的端口
bind(listensock,(struct sockaddr *)&serveraddr,sizeof(struct sockaddr_in));//给套接口绑定地址
listen(listensock,1024); //开始监听
connsock = accept(listensock,(struct sockaddr *)NULL, NULL);
//建立通讯的套接字,accept函数,等待客户端程序使用connect函数的连接
recv(connsock,recvbuff,sizeof(recvbuff),0); //接收服务器的数据
printf("%s\n",recvbuff); //打印接收到的数据
sleep(2);
close(connsock); //关闭通讯套接字
close(listensock); //关闭监听套接字
}
4.Makefile
ifneq ($(KERNELRELEASE),)
obj-m := driver_led.o
else
KDIR := /home/kk/Desktop/forlinx/linux-3.0.1
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm
CROSS_COMPILE=arm-linux-
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif
六、运行结果
按键按下的屏幕显示:
七、心得体会
通过本次实验知道了如何进行主机与服务器的socket通信,并对计算机网络有了更加深入的理解,对于ip地址,子网掩码,网关,dns,DHCP等都有了新的理解。虽然过程中出现了很多问题,但最后还是成功的克服了。