写点什么

Linux 开发 _ 网络编程、网络通信介绍

作者:DS小龙哥
  • 2022 年 6 月 09 日
  • 本文字数:4300 字

    阅读完需:约 14 分钟

这篇文章介绍网络编程的框架,数据收发原理,TCP、UDP 网络编程基础,实现 TCP 服务器与客户端通信,UDP 发送端与接收端通信。

任务 1: 网络编程(下篇实现网页监控)

【1】网络编程


【2】USB 摄像头


【3】HTTP 协议: 搭建 HTTP 服务器。


流程: 网络编程------TCP/IP 协议编程----一套软件协议----->数据结构。



网络编程底层协议: (从网络收发一个字节)


【1】 TCP 协议(C/S): 点对点传输协议。数据传输可靠的。 适合传输大数据。


【2】UDP 协议: 广播方式传输协议 (对特定端口号进行广播)。数据相对 TCP 不可靠的。---不适合传输大数据,传输小块数据。


网络编程的上层协议:


【1】HTTP 协议: 超文本传输协议----网络使用。


【2】FTP 协议: 文件传输协议---传输单文件。


【3】NFS 协议: 文件传输协议----网络文件系统。


TCP 协议编程:


【1】服务器: 等待客户端连接。


【2】客户端: 连接服务器。 QQ 客户端、xxx 游戏客户端。





网络协议: 大端模式。


计算机 IPV4 的端口号范围: 0~65535 。自己编写的程序端口号: >1024

TCP 服务器:

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/fb.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <string.h>#include <time.h>#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h> /* superset of previous */
#define PORT 1234
/*TCP服务器创建:1. 创建socket套接字2. 绑定端口号: 服务器创建3. 设置监听端口的数量: 服务器最大等待连接的客户端总数量4. 等待客户端连接*/int main(int argc,char **argv){ /*1. 创建套接字*/ int server_fd=socket(AF_INET,SOCK_STREAM,0); if(server_fd<0) { printf("TCP服务器:创建套接字创建失败!\n"); return -1; } /*2. 绑定端口号*/ struct sockaddr_in server_addr; memset(&server_addr,0,sizeof(struct sockaddr_in)); server_addr.sin_family=AF_INET; //IPV4 server_addr.sin_port=htons(PORT); //需要填大端格式的端口号数据 server_addr.sin_addr.s_addr=0;//inet_addr("192.168.18.3"); /*0=inet_addr("0.0.0.0") ---表示本地所有IP地址*/ if(bind(server_fd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr_in))!=0) { printf("TCP服务器:绑定端口号失败!\n"); return -2; } printf("struct sockaddr_in=%d\n",sizeof(struct sockaddr_in)); //16 printf("struct sockaddr=%d\n",sizeof(struct sockaddr)); //16 /*3. 设置监听客户端连接的数量*/ listen(server_fd,50); /*4. 等待客户端连接:阻塞*/ struct sockaddr_in client_addr; int addrlen=sizeof(struct sockaddr_in); int client_fd=accept(server_fd,(struct sockaddr *)&client_addr,&addrlen); if(client_fd<0) { printf("服务器提示:等待客户端连接出现错误!\n"); return 0; } /*5. 数据的通信*/ char buff[]="1234567890"; int cnt=write(client_fd,buff,strlen(buff)+1); printf("发送:%d,%s\n",cnt,buff); /*6. 关闭服务器套接字*/ close(server_fd); return 0;}
复制代码

TCP 客户端:

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/fb.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <string.h>#include <time.h>#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h> /* superset of previous */
#define PORT 1234
/*TCP客户端:1. 创建socket套接字2. 连接指定TCP服务器*/int main(int argc,char **argv){ if(argc!=2) { printf("./app server_ip\n"); return 0; } /*1. 创建套接字*/ int client_fd=socket(AF_INET,SOCK_STREAM,0); if(client_fd<0) { printf("TCP客户端:创建套接字创建失败!\n"); return -1; } /*2. 连接服务器*/ struct sockaddr_in server_addr; memset(&server_addr,0,sizeof(struct sockaddr_in)); server_addr.sin_family=AF_INET; //IPV4 server_addr.sin_port=htons(PORT); //需要填大端格式的端口号数据 server_addr.sin_addr.s_addr=inet_addr(argv[1]); if(connect(client_fd,(const struct sockaddr *)&server_addr,sizeof(struct sockaddr_in))!=0) { printf("连接服务器失败!\n"); return -2; } /*3. 数据的通信*/ char buff[100]; int cnt=read(client_fd,buff,100); printf("接收的数据:%d,%s\n",cnt,buff); /*4. 关闭服务器套接字*/ close(client_fd); return 0;}
复制代码

UDP 的函数接口:

【1】数据报收发函数 UDP 使用 recvfrom()函数接收数据,他类似于标准的 read(),但是在 recvfrom()函数中要指明数据的目的地址。


#include <sys/types.h>  #include <sys/socket.h>  ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * from, size_t *addrlen);
复制代码


返回值成功返回接收到数据的长度,负数失败 前三个参数等同于函数 read()的前三个参数,flags 参数是传输控制标志。最后两个参数类似于 accept 的最后两个参数(接收客户端的 IP 地址)。示例:


/*阻塞方式接收数据*/   int len=0;   char buff[1024];   size_t addrlen=sizeof(struct sockaddr);   while(1)   {        len=recvfrom(socketfd,buff,1024,0,(struct sockaddr *)&ClientSocket,&addrlen);        buff[len]='\0';        printf("Rx: %s,len=%d\n",buff,len);        printf("数据发送方IP地址:%s\n",inet_ntoa(ClientSocket.sin_addr));        printf("数据发送方端口号:%d\n",ntohs(ClientSocket.sin_port));          }
复制代码


【2】sendto 函数 UDP 使用 sendto()函数发送数据,他类似于标准的 write(),但是在 sendto()函数中要指明目的地址


#include <sys/types.h>  #include <sys/socket.h>  ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr * to, int addrlen);
复制代码


返回值成功返回发送数据的长度,失败返回-1 前三个参数等同于函数 read()的前三个参数,flags 参数是传输控制标志。参数 to 指明数据将发往的协议地址,他的大小由 addrlen 参数来指定。示例:


/*向UDP协议服务器发送数据*/   ServerSocket.sin_family=PF_INET; //协议   ServerSocket.sin_port=htons(PROT); //端口   ServerSocket.sin_addr.s_addr=inet_addr(argv[1]);  //表示服务器的IP地址   bzero(ServerSocket.sin_zero,8); //初始化空间      char buff[]="1234567890";   int len=0;   while(1)   {       len=sendto(socketfd,buff,strlen(buff),0,(const struct sockaddr*)&ServerSocket,sizeof(struct sockaddr));       printf("Tx: %d\n",len);        sleep(1);         }
复制代码

UDP 接收端:

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/fb.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <string.h>#include <time.h>#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h> /* superset of previous */
#define PORT 1234
/*UDP服务器创建:1. 创建socket套接字2. 绑定端口号: 服务器创建3. 等待接收数据*/
int main(int argc,char **argv){ /*1. 创建套接字*/ int server_fd=socket(AF_INET,SOCK_DGRAM,0); if(server_fd<0) { printf("UDP服务器:创建套接字创建失败!\n"); return -1; } /*2. 绑定端口号*/ struct sockaddr_in server_addr; memset(&server_addr,0,sizeof(struct sockaddr_in)); server_addr.sin_family=AF_INET; //IPV4 server_addr.sin_port=htons(PORT); //需要填大端格式的端口号数据 server_addr.sin_addr.s_addr=0;//inet_addr("192.168.18.3"); /*0=inet_addr("0.0.0.0") ---表示本地所有IP地址*/ if(bind(server_fd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr_in))!=0) { printf("UDP服务器:绑定端口号失败!\n"); return -2; } /*3. 等待数据接收*/ char buff[1024]; struct sockaddr_in client_addr; int addrlen=sizeof(struct sockaddr_in); int recv_len; while(1) { //阻塞方式接收客户端发来的数据 recv_len=recvfrom(server_fd,buff,1024,0,(struct sockaddr *)&client_addr,&addrlen); printf("RX=%d,%s\n",recv_len,buff); //printf(); } /*4. 关闭服务器套接字*/ close(server_fd); return 0;}
复制代码

UDP 发送端:

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/fb.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <string.h>#include <time.h>#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h> /* superset of previous */
#define PORT 1234
/*TDP客户端:1. 创建socket套接字2. 向指定地址发送数据*/int main(int argc,char **argv){ if(argc!=2) { printf("./app server_ip\n"); return 0; } /*1. 创建套接字*/ int client_fd=socket(AF_INET,SOCK_DGRAM,0); if(client_fd<0) { printf("TCP客户端:创建套接字创建失败!\n"); return -1; } /*2. 向UDP服务器发送数据*/ char buff[]="1234567890"; int send_len; struct sockaddr_in server_addr; memset(&server_addr,0,sizeof(struct sockaddr_in)); server_addr.sin_family=AF_INET; //IPV4 server_addr.sin_port=htons(PORT); //需要填大端格式的端口号数据 server_addr.sin_addr.s_addr=inet_addr(argv[1]); while(1) { //向服务器发送数据 send_len=sendto(client_fd,buff,strlen(buff)+1,0,(const struct sockaddr *)&server_addr,sizeof(struct sockaddr_in)); printf("TX:%d,%s\n",send_len,buff); sleep(1); } /*3. 关闭客户端套接字*/ close(client_fd); return 0;}
复制代码


发布于: 刚刚阅读数: 3
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
Linux开发_网络编程、网络通信介绍_6月月更_DS小龙哥_InfoQ写作社区