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

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

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

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

【1】网络编程

【2】USB摄像头

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

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

img

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

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

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

网络编程的上层协议:

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

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

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

TCP协议编程:

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

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

img

img

img

网络协议: 大端模式。

计算机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;
 }
复制代码

猜你喜欢

转载自juejin.im/post/7107050231266541599