linux系统编程和网络编程,linux网络高级编程

  linux系统编程和网络编程,linux网络高级编程

  一、Linux网络概述

  Linux为用户提供了完善而强大的网络功能。

  1.完善的内置网络。其他操作系统不包含与内核结合如此紧密的网络部分。

  2.Linux免费提供大量支持互联网的软件。互联网是在Unix领域建立并繁荣起来的。这方面用Linux还是挺方便的。用户可以使用Linux通过互联网与世界上的其他人交流。

  3.用户可以通过一些Linux命令传输内部信息或文件。

  4.支持远程访问

  5.安全可靠,采用多种安全技术措施为用户提供安全保障。

  网络模型

  第一部分是网络层协议:互联网协议(IP)、网络控制消息协议(ICMP)和地址解析协议(ARP)。

  第二部分是传输层协议:传输控制协议(TCP)(面向连接的可靠)和用户数据报协议(UDP)(不可靠未连接)。

  第三部分是应用层协议:Telnet、FTP和TFTP、简单文件传输协议(SMTP)和域名服务(DNS)。

  协议封装

  使用wireshark进行数据包捕获分析

  逐层封装:以太网IP TCP

  以太网-IP- TCP- HTTP

  以太网数据包

  互联网协议

  IP的功能:数据传输、寻址、路由、数据报文分段。

  主要目的是为数据输入输出网络提供基本算法,为高层协议提供无连接传输服务。这意味着在将数据提交给接收站点之前,IP不会在传输站点和接收站点之间建立对话。它只封装和传输数据,不向发送方或接收方报告数据包状态,也不处理遇到的故障。

  它由协议头和协议数据组成。

  TCP协议

  是一种重要的传输层协议,其目的是允许与网络上的其他节点可靠地交换数据。它可以提供端口号解码,以识别主机应用程序并完成可靠的数据传输。

  TCP有一个严格的内置错误检查算法来确保数据的完整性。

  TCP是一种面向字节的顺序协议,这意味着数据包中的每个字节都分配有一个序列号,每个数据包都分配有一个序列号。

  UDP协议

  它也是传输层协议,是一种无连接、不可靠的传输服务。在接收数据时,它不向发送方提供确认信息,不提供输入包的顺序,在出现包丢失或包重复的情况下,也不会向发送方发送错误消息。因为它在执行函数时开销低,所以执行速度比TCP快。

  二、Linux网络编程基础

  窝

  Linux中的网络编程是通过Socket实现的,Socket是一种文件描述符。

  三种类型

  1.流式套接字(SOCK_STREAM)

  它可以提供可靠的、面向连接的通信流,并且它使用TCP协议,这保证了数据传输的正确性和顺序性。

  2.数据报套接字(SOCK_DGRAM)

  定义了无连接服务。数据通过独立的消息传输,乱序,可靠,无错。它使用数据报协议UDP。

  3.原始套接字(SOCK_RAW)

  允许使用IP协议,主要用于测试新的网络协议等。

  网络地址

  想要的是

  {

  u _ short sa _ family

  char sa _ data[14];

  } sa_family:协议族,形式为‘AF _ XXX’,如AF_INET(IP协议族)

  Sa _ data: 14字节特定协议地址

  地址结构

  另一个结构

  地址转换

  IP地址通常用带点的数字表示,而结构体in_addr中love使用的IP地址用32位整数表示。

  int inet_aton(const char *cp,struct in_addr *inp)

  char * inet_ntoa(结构输入地址输入)

  前者是32位整数,后者是32位数字——字符串。

  字节顺序

  在同一网络上使用Big endian,低位字节先传输。

  当内部字节存储顺序与网络字节顺序不同时,需要进行转换。

  为什么,示例:

  转换:

  Htons:将无符号短类型从主机顺序转换为网络顺序(发送)

  Htonl:将无符号长整型从主机顺序转换为网络顺序(发送)

  Ntohs:将无符号短类型从网络序列转换为主机序列(接收)

  Ntohl:将无符号长整型从网络序列转换为主机序列(接收)

  和IP主机名

  套接字编程功能

  插座:创建一个窝

  绑定:用于绑定互联网协议(互联网协议)地址和端口号到窝

  连接:用于与服务器建立连接

  听着:设置服务器能处理的最大连接要求

  接受:用来等待来自服务端的窝连接请求

  发送:发送数据

  建议:接收数据

  三、基于三氯苯酚

  服务器

  客户端

  通信模型

  示例代码tcp_server.c

  #包含标准库

  #包含标准视频

  #包含错误号h

  #包含字符串。h

  #包含netdb.h

  #包含sys/types.h

  #包含netinet/in.h

  #包含sys/socket.h

  #包括arpa/inet.h

  #定义端口号3333

  int main(int argc,char *argv[])

  {

  int sockfd,new _ fd

  结构sockaddr _ in server _ addr

  客户端地址中的结构sockaddr _ in

  int sin _ size

  int nbytes

  茶缓冲区[1024];

  /* 服务器端开始建立套接字描述符*/

  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)//AF _ INET:IP v4;套接字流:TCP

  {

  fprintf(stderr,套接字错误:%s\n\a ,strerror(errno));

  出口(1);

  }

  /* 服务器端填充套接字地址结构*/

  bzero( server_addr,sizeof(struct sockaddr _ in));//初始化,置0

  服务器地址。sin _家庭=AF _ INET//互联网

  服务器地址。sin _ addr。s _ addr=htonl(在addr _ ANY中);//(将本机器上的长的数据转化为网络上的长的数据)和任何主机通信//INADDR_ANY表示可以接收任意互联网协议(互联网协议)地址的数据,即绑定到所有的互联网协议(互联网协议)

  //server _ addr。sin _ addr。s _ addr=inet _ addr( 192。168 .1 .1 );//用于绑定到一个固定IP,inet_addr用于把数字加格式的互联网协议(互联网协议的缩写)转化为整形互联网协议(互联网协议的缩写)

  server_addr.sin_port=htons(端口号);//(将本机器上的短的数据转化为网络上的短的数据)端口号

  /* 捆绑套接字描述符到互联网协议(互联网协议)地址*/

  if(bind(sockfd,(struct sockaddr *)( server_addr),sizeof(struct sockaddr))==-1)

  {

  fprintf(stderr,绑定错误:%s\n\a ,strerror(errno));

  出口(1);

  }

  /* 设置允许连接的最大客户端数*/

  if(listen(sockfd,5)==-1)

  {

  fprintf(stderr,侦听错误:%s\n\a ,strerror(errno));

  出口(1);

  }

  while(1)

  {

  /* 服务器阻塞,直到客户程序建立连接*/

  sin _ size=sizeof(struct sockaddr _ in);

  if((new_fd=accept(sockfd,(struct sockaddr *)( client_addr),sin_size))==-1)

  {

  fprintf(stderr,接受错误:%s\n\a ,strerror(errno));

  出口(1);

  }

  fprintf(stderr,服务器从%s获取连接\n ,inet _ ntoa(client _ addr。sin _ addr));//将网络地址转换成。字符串

  if((nbytes=read(new_fd,buffer,1024))==-1)

  {

  fprintf(stderr,读取错误:%s\n ,strerror(errno));

  出口(1);

  }

  buffer[nbytes]= \ 0 ;

  printf(服务器接收到%s\n ,缓冲区);

  /* 这个通讯已经结束*/

  close(new _ FD);

  /* 循环下一个*/

  }

  /* 结束通讯*/

  关闭(sockfd);

  退出(0);

  } 示例代码tcp_client.c

  #包含标准库

  #包含标准视频

  #包含错误号h

  #包含字符串。h

  #包含netdb.h

  #包含sys/types.h

  #包含netinet/in.h

  #包含sys/socket.h

  #包括arpa/inet.h

  #定义端口号3333

  int main(int argc,char *argv[])

  {

  int sockfd

  茶缓冲区[1024];

  结构sockaddr _ in server _ addr

  结构主机*主机

  /* 使用主机名查询宿主名字*/

  如果(argc!=2)

  {

  fprintf(stderr,用法:%s主机名\a\n ,argv[0]);

  出口(1);

  }

  if((host=gethostbyname(argv[1])==NULL)

  {

  fprintf(stderr, Gethostname error \ n );

  出口(1);

  }

  /* 客户程序开始建立套接字描述符*/

  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)//AF _ INET:Internet;套接字流:TCP

  {

  fprintf(stderr,套接字错误:%s\a\n ,strerror(errno));

  出口(1);

  }

  /* 客户程序填充服务端的资料*/

  bzero( server_addr,sizeof(server _ addr));//初始化,置0

  服务器地址。sin _家庭=AF _ INET//IPV4

  server_addr.sin_port=htons(端口号);//(将本机器上的短的数据转化为网络上的短的数据)端口号

  服务器地址。sin _ addr=*((struct in _ addr *)host-h _ addr);//IP地址

  /* 客户程序发起连接请求*/

  if(connect(sockfd,(struct sockaddr *)( server_addr),sizeof(struct sockaddr))==-1)

  {

  fprintf(stderr,连接错误:%s\a\n ,strerror(errno));

  出口(1);

  }

  /* 连接成功了*/

  printf(请输入char:\ n );

  /* 发送数据*/

  fgets(buffer,1024,stdin);

  write(sockfd,buffer,strlen(buffer));

  /* 结束通讯*/

  关闭(sockfd);

  退出(0);

  } 运行结果:客户端

  [gyy @本地主机TCP]$ gcc TCP _ client。转交TCP _客户端

  [gyy@localhost TCP]$ ./TCP _客户端192.168.1.30

  请输入字符:

  12345运行结果:服务器

  [gyy @ localhost TCP]$ gcc TCP _ server。c-o TCP服务器

  [gyy@localhost TCP]$ ./tcp_server

  服务器从192.168.1.30获取连接

  服务器收到12345代码分析:服务器三次阻塞:第一次等待连接,第二次等待读,第三次客户端发送完成后断开连接服务器等待连接

  四、基于用户数据报协议(用户数据报协议)

  客户端

  通信模型

  示例代码udp_server.c

  #包含标准库

  #包含标准视频

  #包含错误号h

  #包含字符串。h

  #包括unistd.h

  #包含netdb.h

  #包含sys/socket.h

  #包含netinet/in.h

  #包含sys/types.h

  #包括arpa/inet.h

  #定义服务器端口8888

  #定义最大消息大小1024

  void udps_respon(int sockfd)

  {

  结构sockaddr _ in地址

  int addrlen,n;

  char MSG[MAX _ MSG _ SIZE];

  while(1)

  { /* 从网络上读,并写到网络上*/

  bzero(msg,sizeof(msg));//初始化,清零

  addrlen=sizeof(struct sockaddr);

  n=recvfrom(sockfd,msg,MAX_MSG_SIZE,0,(struct sockaddr*) addr,addrlen);//从客户端接收消息

  msg[n]=0;

  /* 显示服务端已经收到了信息*/

  fprintf(标准输出,服务器已收到“%s”,消息);//显示消息

  }

  }

  int main(void)

  {

  int sockfd

  结构sockaddr _ in地址

  /* 服务器端开始建立窝描述符*/

  sockfd=socket(AF_INET,SOCK_DGRAM,0);

  if(sockfd 0)

  {

  fprintf(stderr,套接字错误:%s\n ,strerror(errno));

  出口(1);

  }

  /* 服务器端填充套接字地址结构*/

  bzero( addr,sizeof(struct sockaddr _ in));

  地址. sin _ family=AF _ INET

  地址。sin _ addr。s _ addr=htonl(在addr _ ANY中);

  地址。sin _ PORT=htons(SERVER _ PORT);

  /* 捆绑套接字描述符*/

  if(bind(sockfd,(struct sockaddr *) addr,sizeof(struct sockaddr_in)) 0)

  {

  fprintf(stderr,绑定错误:%s\n ,strerror(errno));

  出口(1);

  }

  UDPS _ respon(sockfd);//进行读写操作

  关闭(sockfd);

  } 示例代码udp_client.c

  #包含标准库

  #包含标准视频

  #包含错误号h

  #包含字符串。h

  #包括unistd.h

  #包含netdb.h

  #包含sys/socket.h

  #包含netinet/in.h

  #包含sys/types.h

  #包括arpa/inet.h

  #定义服务器端口8888

  #定义MAX_BUF_SIZE 1024

  void udpc_requ(int sockfd,const struct sockaddr_in *addr,int len)

  {

  char buff[MAX _ BUF _ SIZE];

  int n;

  while(1)

  { /* 从键盘读入,写到服务端*/

  printf(请输入char:\ n );

  fgets(buffer,MAX_BUF_SIZE,stdin);

  sendto(sockfd,buffer,strlen(buffer),0,addr,len);

  bzero(buffer,MAX _ BUF _ SIZE);

  }

  }

  int main(int argc,char **argv)

  {

  int sockfd

  结构sockaddr _ in地址

  如果(argc!=2)

  {

  fprintf(stderr,用法:%s server_ip\n ,argv[0]);

  出口(1);

  }

  /* 建立套接字描述符*/

  sockfd=socket(AF_INET,SOCK_DGRAM,0);

  if(sockfd 0)

  {

  fprintf(stderr,套接字错误:%s\n ,strerror(errno));

  出口(1);

  }

  /* 填充服务端的资料*/

  bzero( addr,sizeof(struct sockaddr _ in));

  地址. sin _ family=AF _ INET

  地址。sin _ PORT=htons(SERVER _ PORT);

  if(inet_aton(argv[1],addr.sin_addr) 0) /*inet_aton函数用于把字符串型的互联网协议(互联网协议)地址转化成网络2进制数字*/

  {

  fprintf(stderr, Ip错误:%s\n ,strerror(errno));

  出口(1);

  }

  udpc_requ(sockfd,addr,sizeof(struct sockaddr _ in));//进行读写操作

  关闭(sockfd);

  } 运行结果:客户端

  [gyy @ localhost UDP]$ gcc UDP _ client。转交UDP _客户端

  [gyy@localhost UDP]$ ./UDP _客户端192.168.1.30

  请输入字符:

  你好

  请输入字符:

  世界

  请输入字符:运行结果:服务器

  [gyy @ localhost UDP]$ gcc UDP _ server。转交UDP _服务器

  [gyy@localhost UDP]$ ./udp_server

  服务器收到你好

  服务器已接收世界五、服务器模型在网络程序里,一般来说都是许多客户对应一个服务器,两种服务器模型

  循环服务器、并发服务器

  三氯苯酚循环服务器

  三氯苯酚循环服务器一次只能处理一个客户端的请求,只有在这个客户的所有请求都满足后,服务器才可以继续后面的请求。这样如果有一个客户端占住了服务器不放时,其它的客户机都不能工作了,因此三氯苯酚服务器一般很少用循环服务器模型

  示例代码:tcp_server_fork.c

  #包含标准库

  #包含标准视频

  #包含错误号h

  #包含字符串。h

  #包含netdb.h

  #包含sys/types.h

  #包含netinet/in.h

  #包含sys/socket.h

  #包括arpa/inet.h

  #定义我的端口3333

  int main(int argc,char **argv)

  {

  int listen_fd,accept _ fd

  客户端地址中的结构sockaddr _ in

  int n;

  if((listen_fd=socket(AF_INET,SOCK_STREAM,0)) 0)

  {

  printf(套接字错误:%s\n\a ,strerror(errno));

  出口(1);

  }

  bzero( client_addr,sizeof(struct sockaddr _ in));

  客户端_地址。罪恶_家庭=AF _ INET

  客户端地址。sin _ PORT=htons(MY _ PORT);

  客户端地址。sin _ addr。s _ addr=htonl(在addr _ ANY中);

  n=1;

  /* 如果服务器终止后,服务器可以第二次快速启动而不用等待一段时间*/

  setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,n,sizeof(int));

  if(bind(listen_fd,(struct sockaddr *) client_addr,sizeof(client_addr)) 0)

  {

  printf(绑定错误:%s\n\a ,strerror(errno));

  出口(1);

  }

  listen(listen_fd,5);

  while(1)

  {

  accept_fd=accept(listen_fd,NULL,NULL);

  if((accept_fd 0) (errno==EINTR))

  继续;

  else if(accept_fd 0)

  {

  printf(接受错误:%s\n\a ,strerror(errno));

  继续;

  }

  if((n=fork())==0)

  {

  //printf( OK \ n );

  /* 子进程处理客户端的连接*/

  茶缓冲区[1024];

  关闭(listen _ FD);

  n=read(accept_fd,buffer,1024);

  write(accept_fd,buffer,n);

  printf(接收:%s\n ,缓冲区);

  close(accept _ FD);

  退出(0);

  }

  else if(n 0)

  printf(Fork Error:%s\n\a ,strerror(errno));

  close(accept _ FD);

  }

  } 示例代码:tcp_client.c

  #包含标准库

  #包含标准视频

  #包含错误号h

  #包含字符串。h

  #包含netdb.h

  #包含sys/types.h

  #包含netinet/in.h

  #包含sys/socket.h

  #包括arpa/inet.h

  #定义端口号3333

  int main(int argc,char *argv[])

  {

  int sockfd

  茶缓冲区[1024];

  结构sockaddr _ in server _ addr

  结构主机*主机

  /* 使用主机名查询宿主名字*/

  如果(argc!=2)

  {

  fprintf(stderr,用法:%s主机名\a\n ,argv[0]);

  出口(1);

  }

  if((host=gethostbyname(argv[1])==NULL)

  {

  fprintf(stderr, Gethostname error \ n );

  出口(1);

  }

  /* 客户程序开始建立套接字描述符*/

  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)//AF _ INET:Internet;套接字流:TCP

  {

  fprintf(stderr,套接字错误:%s\a\n ,strerror(errno));

  出口(1);

  }

  /* 客户程序填充服务端的资料*/

  bzero( server_addr,sizeof(server _ addr));//初始化,置0

  服务器地址。sin _家庭=AF _ INET//IPV4

  server_addr.sin_port=htons(端口号);//(将本机器上的短的数据转化为网络上的短的数据)端口号

  服务器地址。sin _ addr=*((struct in _ addr *)host-h _ addr);//IP地址

  /* 客户程序发起连接请求*/

  if(connect(sockfd,(struct sockaddr *)( server_addr),sizeof(struct sockaddr))==-1)

  {

  fprintf(stderr,连接错误:%s\a\n ,strerror(errno));

  出口(1);

  }

  /* 连接成功了*/

  printf(请输入char:\ n );

  /* 发送数据*/

  fgets(buffer,1024,stdin);

  write(sockfd,buffer,strlen(buffer));

  /* 结束通讯*/

  关闭(sockfd);

  退出(0);

  }

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • Linux计划任务的命令是什么,linux 任务,linux系统中计划任务介绍
  • linux系统设置免密登录,linux免密钥登录
  • linux系统设置免密登录,linux免密钥登录,Linux下实现免密码登录(超详细)
  • Linux系统查看版本,linux系统查看系统版本
  • Linux系统查看版本,linux系统查看系统版本,Linux查看系统版本的方法汇总
  • linux操作系统的安装与配置,linux系统安装与配置教程
  • linux操作系统的安装与配置,linux系统安装与配置教程,Linux操作系统安装图文配置教程详细版
  • Linux基本网络配置命令,linux网络配置,Linux系统配置网络详细介绍
  • linux命令日志,linux系统日志怎么看
  • linux命令日志,linux系统日志怎么看,Linux系统中日志详细介绍
  • linux 服务配置文件,linux服务管理命令,Linux系统配置(服务控制)详细介绍
  • debian 命令行安装,debian安装软件方式,基于Debian的linux系统软件安装命令详解 (推荐)
  • ,,查看Linux系统是32位还是64位的方法总结
  • ,,Linux系统设置PATH环境变量(3种方法)
  • ,,Linux系统的修复模式(单用户模式)
  • 留言与评论(共有 条评论)
       
    验证码: