实验五

实验五 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等都有了新的理解。虽然过程中出现了很多问题,但最后还是成功的克服了。

原文地址:https://www.cnblogs.com/qingjielaojiu/p/15737828.html