热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Linux网络编程--2.初等网络函数介绍(TCP)

文章标题:Linux网络编程--2.初等网络函数介绍(TCP)。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类

  Linux系统是通过提供套接字(socket)来进行网络编程的.网络程序通过socket和其它几个函数的调用,会返回一个 通讯的文件描述符,我们可以将这个描述符看成普通的文件的描述符来操作,这就是linux的设备无关性的 好处.我们可以通过向描述符读写操作实现网络之间的数据交流.
  
  2.1 socket
  int socket(int domain, int type,int protocol)
  
  domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等). AF_UNIX只能够用于单一的Unix系统进程间通信,而AF_INET是针对Internet的,因而可以允许在远程 主机之间通信(当我们 man socket时发现 domain可选项是 PF_*而不是AF_*,因为glibc是posix的实现 所以用PF代替了AF,不过我们都可以使用的).
  
  type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等) SOCK_STREAM表明我们用的是TCP协议,这样会提供按顺序的,可靠,双向,面向连接的比特流. SOCK_DGRAM 表明我们用的是UDP协议,这样只会提供定长的,不可靠,无连接的通信.
  
  protocol:由于我们指定了type,所以这个地方我们一般只要用0来代替就可以了 socket为网络通讯做基本的准备.成功时返回文件描述符,失败时返回-1,看errno可知道出错的详细情况.
  
  2.2 bind
  int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
  
  sockfd:是由socket调用返回的文件描述符.
  
  addrlen:是sockaddr结构的长度.
  
  my_addr:是一个指向sockaddr的指针. 在中有 sockaddr的定义
  
  struct sockaddr{
  unisgned short as_family;
  char sa_data[14];
  };
  
  不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct sockaddr_in) 来代替.在中有sockaddr_in的定义
  struct sockaddr_in{
  unsigned short sin_family;
  unsigned short int sin_port;
  struct in_addr sin_addr;
  unsigned char sin_zero[8];
  
  我们主要使用Internet所以sin_family一般为AF_INET,sin_addr设置为INADDR_ANY表示可以 和任何的主机通信,sin_port是我们要监听的端口号.sin_zero[8]是用来填充的. bind将本地的端口同socket返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket一样
  
  2.3 listen
  int listen(int sockfd,int backlog)
  
  sockfd:是bind后的文件描述符.
  
  backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时, 使用这个表示可以介绍的排队长度. listen函数将bind的文件描述符变为监听套接字.返回的情况和bind一样.
  
  2.4 accept
  int accept(int sockfd, struct sockaddr *addr,int *addrlen)
  
  sockfd:是listen后的文件描述符.
  
  addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了. bind,listen和accept是服务器端用的函数,accept调用时,服务器端的程序会一直阻塞到有一个 客户程序发出了连接. accept成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了. 失败时返回-1
  
  2.5 connect
  int connect(int sockfd, struct sockaddr * serv_addr,int addrlen)
  
  sockfd:socket返回的文件描述符.
  
  serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址
  
  addrlen:serv_addr的长度
  
  connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符 失败时返回-1.
  
  2.6 实例
  
  服务器端程序
  
  
  /******* 服务器程序 (server.c) ************/
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  
  int main(int argc, char *argv[])
  {
  int sockfd,new_fd;
  struct sockaddr_in server_addr;
  struct sockaddr_in client_addr;
  int sin_size,portnumber;
  char hello[]="Hello! Are You Fine?\n";
  
  if(argc!=2)
  {
  fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);
  exit(1);
  }
  
  if((portnumber=atoi(argv[1]))<0)
  {
  fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);
  exit(1);
  }
  
  /* 服务器端开始建立socket描述符 */
  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
  {
  fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
  exit(1);
  }
  
  /* 服务器端填充 sockaddr结构 */
  bzero(&server_addr,sizeof(struct sockaddr_in));
  server_addr.sin_family=AF_INET;
  server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
  server_addr.sin_port=htons(portnumber);
  
  /* 捆绑sockfd描述符 */
  if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
  {
  fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
  exit(1);
  }
  
  /* 监听sockfd描述符 */
  if(listen(sockfd,5)==-1)
  {
  fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
  exit(1);
  }
  
  while(1)
  {
  /* 服务器阻塞,直到客户程序建立连接 */
  sin_size=sizeof(struct sockaddr_in);
  if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)
  {
  fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
  exit(1);
  }
  
  fprintf(stderr,"Server get connection from %s\n",
  inet_ntoa(client_addr.sin_addr));
  if(write(new_fd,hello,strlen(hello))==-1)
  {
  fprintf(stderr,"Write Error:%s\n",strerror(errno));
  exit(1);
  }
  /* 这个通讯已经结束 */
  close(new_fd);
  /* 循环下一个 */
  }
  close(sockfd);
  exit(0);
  }
  
  客户端程序
  
  /******* 客户端程序 client.c ************/
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  
  int main(int argc, char *argv[])
  {
  int sockfd;
  char buffer[1024];
  struct sockaddr_in server_addr;
  struct hostent *host;
  int portnumber,nbytes;
  
  if(argc!=3)
  {
  fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);
  exit(1);
  }
  
  if((host=gethostbyname(argv[1]))==NULL)
  {
  fprintf(stderr,"Gethostname error\n");
  exit(1);
  }
  
  if((portnumber=atoi(argv[2]))<0)
  {
  fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);
  exit(1);
  }
  
  /* 客户程序开始建立 sockfd描述符 */
  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
  {
  fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));
  exit(1);
  }
  
  /* 客户程序填充服务端的资料 */
  bzero(&server_addr,sizeof(server_addr));
  server_addr.sin_family=AF_INET;
  server_addr.sin_port=htons(portnumber);
  server_addr.sin_addr=*((struct in_addr *)host->h_addr);
  
  /* 客户程序发起连接请求 */
  if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
  {
  fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));
  exit(1);
  }
  
  /* 连接成功了 */
  if((nbytes=read(sockfd,buffer,1024))==-1)
  {
  fprintf(stderr,"Read Error:%s\n",strerror(errno));
  exit(1);
  }
  buffer[nbytes]='\0';
  printf("I have received:%s\n",buffer);
  /* 结束通讯 */
  close(sockfd);
  exit(0);
  }
  
  MakeFile
  这里我们使用GNU 的make实用程序来编译. 关于make的详细说明见 Make 使用介绍
  
  ######### Makefile ###########
  all:server client
  server:server.c
  gcc $^ -o $@
  client:client.c
  gcc $^ -o $@
  
  运行make后会产生两个程序server(服务器端)和client(客户端) 先运行./server portnumber& (portnumber随便取一个大于1204且不在/etc/services中出现的号码 就用8888好了),然后运行 ./client localhost 8888 看看有什么结果. (你也可以用telnet和netstat试一试.) 上面是一个最简单的网络程序,不过是不是也有点烦.上面有许多函数我们还没有解释. 我会在下一章进行的详细的说明.
  
  2.7 总结
  总的来说网络程序是由两个部分组成的--客户端和服务器端.它们的建立步骤
推荐阅读
  • 三、寻找恶意IP并用iptables禁止掉找出恶意连接你的服务器80端口的IP,直接用iptables来drop掉它;这里建议写脚本来运行, ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 概述H.323是由ITU制定的通信控制协议,用于在分组交换网中提供多媒体业务。呼叫控制是其中的重要组成部分,它可用来建立点到点的媒体会话和多点间媒体会议 ... [详细]
  • POCOCLibraies属于功能广泛、轻量级别的开源框架库,它拥有媲美Boost库的功能以及较小的体积广泛应用在物联网平台、工业自动化等领域。POCOCLibrai ... [详细]
  • Linux防火墙配置—允许转发
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • UDP千兆以太网FPGA_verilog实现(四、代码前期准备UDP和IP协议构建)
    UDP:userDatagramprotocol用户数据报协议无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETFRFC76 ... [详细]
  • SQL Server 2008 到底需要使用哪些端口?
    SQLServer2008到底需要使用哪些端口?-下面就来介绍下SQLServer2008中使用的端口有哪些:  首先,最常用最常见的就是1433端口。这个是数据库引擎的端口,如果 ... [详细]
author-avatar
1397527971_3148ce
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有