本帖最后由 ぉ沙皮狗的忧伤 于 2021-3-3 18:37 编辑
网络应用编程:实现跨机器跨操作系统通信封装:TCP/IP协议
三要素:
IP地址:网络主机唯一标识,IP通过路由寻找网络接受主机
端口:指定接受网络数据的应用程序(端口)
服务类型:可靠与不可靠传输
网络架构的模型:
TCP协议:
是一种面向连接的传输协议,它能提高可靠性通信(即数据无误,数据无丢失,数据无重复性),适用于传输质量较高,以及大量数据通信
UDP协议:
用户数据报协议,是不可靠传输协议,在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输,适用发送小尺寸数据,应答较困难的网络中适用,适用于广播/组播式的通信中,流媒体的数据传输
tcp sever端代码编写
1、添加头文件
- //1、添加头文件
- #include <stdio.h>
- #include <strings.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
-
- #include <netinet/ip.h>
- #include <netinet/in.h>
-
- #include <arpa/inet.h>
复制代码
2、创建流失套接字- //创建流失套接字
- //参数1-----地址族,AF_INET网络协议族
- //参数2-----套接字类型,SOCK_STREAM使用TCP
- //参数3-----protocol参数通常设备0
- //返回值----成功socket ID,出错返回-1
- serfd = socket( AF_INET, SOCK_STREAM, 0);
- if(serfd < 0){
- perror("socket failed!\n");
- exit(1);
- }
复制代码
3、绑定本地IP地址和指定接收数据端口
- struct sockaddr_in self;
-
- //初始化self结构体
- bzero( &self, sizeof(self));
-
- self.sin_family = AF_INET; //选择ipv4协议
- self.sin_port = htons(6666); //转换为网络字节序端口
- self.sin_addr.s_addr = inet_addr("172.18.21.222");
-
- //绑定本机地址和端口
- //参数1----文件描述符
- //参数2----sockaddr_in结构,描述本机的端口和ip地址
- //参数3----sockaddr地址结构体的长度
- //返回值0或-1
- ret = bind( serfd, (struct sockaddr *)&self, sizeof(self));
- if(ret < 0){
- perror("bind failed!\n");
- exit(1);
- }
复制代码
4、设置为监听模式:被动链接- //4、设置为监听模式:被动链接
- //listen监听套接字
- //参数1-----被监听的套接字
- //参数2-----指定正在等待的最大队列长度
- //返回值----0或-1
- ret = listen( serfd, 5);
- if(ret < 0){
- perror("listen failed!\n");
- exit(1);
- }
-
- struct sockaddr_in cli;
- bzero( &cli, sizeof(cli));
-
- printf("wait client!\n");
复制代码
5、等待客户端链接- //等待客户端链接
- //accept建立连接
- //参数1-----文件描述符
- //参数2-----sockaddr_in结构,描述本机的端口和ip地址
- //参数3-----地址长度
- //返回值,成功已建立的套接字,失败返回-1
- int newfd = accept( serfd, (struct sockaddr *)&cli, sizeof(cli));
- if(newfd < 0){
- perror("accpet failed!\n");
- exit(1);
- }
-
- //inet_ntoa-----将32位网络字节序二进制地址转换成点分十进制的字符串
- printf("new client ip = %s port = %d ok\n", inet_ntoa(cli.sin_addr),\
- ntohs(cli.sin_port));
-
- char buf[128];
复制代码
6、读写数据
- //读写数据
- while(1){
- //初始化buf数组
- bzero( buf, 128);
- ret = read( newfd, buf, 127);
- if(ret < 0){
- perror("read newfd failed!\n");
- exit(1);
- }
-
- if(ret == 0){ //客户端关闭
- printf("server close\n");
- break;
- }
-
- printf("ret = %d buf:%s\n", ret, buf);
-
- }
复制代码
tcp 客户端代码编写
1、添加头文件- #include <stdio.h>
- #include <strings.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
-
- #include <netinet/in.h>
- #include <netinet/ip.h>
-
- #include <arpa/inet.h>
复制代码
2、建立流失套接字
- //建立流失套接字
- //创建流失套接字
- //参数1-----地址族,AF_INET网络协议族
- //参数2-----套接字类型,SOCK_STREAM使用TCP
- //参数3-----protocol参数通常设备0
- //返回值----成功socket ID,出错返回-1
- clifd = socket( AF_INET, SOCK_STREAM, 0);
- if(clifd < 0){
- perror("socket failed!\n");
- exit(1);
- }
复制代码
3、主动连接服务器:指定服务器IP和接收端口
- //主动连接服务器:指定服务器IP和接收端口
- struct sockaddr_in ser;
-
- //初始化ser结构体
- bzero( &ser, sizeof(ser));
-
- ser.sin_family = AF_INET; //选择IPV4协议
- ser.sin_port = htons(6666); //要连接的服务器端口
- ser.sin_addr.s_addr = inet_addr("172.18.21.222"); //服务器的ip
复制代码
4、连接服务器
- //参数1----文件描述符
- //参数2----sockaddr_in结构,描述本机的端口和ip地址
- //参数3----sockaddr地址结构体的长度
- //返回值0或-1
- ret = connect( clifd, (struct sockaddr *)&ser, sizeof(ser));
- if(ret < 0){
- perror("connetc failed!\n");
- exit(1);
- }
-
- printf("connect server ok\n");
- char buf[128];
-
复制代码
5、发送数据到服务器- //发送数据到服务器
- while(1){
- fprintf( stderr, "input:");
- //初始化buf
- bzero( buf, 128);
- //从键盘获取数值
- fgets( buf, 127, stdin);
-
- //将buf里面的值通过clifd套接字发送到服务器中
- ret = write( clifd, buf, strlen(buf));
- if(ret < 0){
- perror("write failed!\n");
- exit(1);
- }
-
- //判断是否输入quit,如果输入了,则退出
- if(!strncmp( buf, "quit", 4)){
- break;
- }
-
- }
复制代码
编译并运行使用交叉编译器编译sever代码,在开发板上运行,使用gcc编译器编译client代码,在Ubuntu上运行
先在板卡运行sever端,等待连接
在ubuntu运行client端建立连接发送数据,
代码在附件中
|