UNIX网络编程--简介(一)【转】

本文转载自:http://blog.csdn.net/yusiguyuan/article/details/11760187

一、概述

a) 在编写与计算机通信的程序时,首先要确定的就是和计算机通信的协议,从高层次来确定通信由哪个程序发起以及响应在合适产生。大多数网络应用按照划分成客户和服务器来组织。在设计网络应用时,确定总是由客户发起请求往往能够简化协议和程序本身。当然一个较为复杂的网络应用还需要异步回调通信,也就是由服务器向客户发起请求消息。

i. 在本书原著上多次提到客户(client)和服务器(server)这两个术语。但是他们在具体上下文的含义不同,有的是指静态的程序(客户程序和服务器程序),有的是指动态的进程(客户进程和服务器进程),有时指运行进程的主机(客户主机和服务器主机)。

ii.可认为客户与服务器之间是通过某个网络协议通信的,但实际上,这样的通信通常涉及到多个网络协议层。本书的焦点是TCP/IP协议簇,也称为网际协议簇。举例,WEB客户与服务器之间使用TCP(Transmission Control Protocol,传输控制协议)通信。TCP又转而使用IP(InternetProtocol,网际协议)通信,IP再通过某种形式的数据链路层通信。

尽管客户与服务器之间使用某个应用协议通信,传输层却使用TCP通信。数据流的流向在一端从上到下,在另一端从下到上。通常,客户和服务器通常是用户进程,

而TCP和IP协议通常是内核中协议栈的一部分。其中七层OSI模型(物理层、数据链路层、网络层、传输层、表示层、会话层、应用层)。

上图讲述的是处于同一个局域网里的通信情况,在不同局域网的情况是:通过路由器连接到广域网。(路由器是广域网的架构设备)

关于结构体struct sockaddr,也就是通过套接字地址结构,每当一个套接字函数需要一个指向某个套接字地址结构的指针时,这个指针必须强制类型转换成一个指向通过套接字地址结构的指针。

二、一个简单的时间获取客户程序

本章在举例说明的时候,使用了获取时间的服务器函数之类的东西,这是一个函简单的程序,按照的基本的TCP客户/服务流程交互,在服务端在填写字符的时候使用了函数snprintf,这个函数和sprintf的功能相似。调用sprintf无法检查目的缓冲区是否溢出。Snprintf要求其第二个参数指定目的缓冲区的大小,因此可确保该缓冲区不溢出。

单个处理一个客户的服务器程序称为迭代服务器,因为对于每个客户它都迭代执行一次。同时能处理多个客户的称为并发服务器。

下面是客户程序的main函数:

[cpp] view plain copy

  1. #define MAXLIEN 1024
  2. int main(int argc,char *argv[])
  3. {
  4. int i,sockfd,n;
  5. struct sockaddr_in serveraddr;
  6. char recvline[MAXLIEN+1];
  7. sockfd=socket(AF_INET,SOCK_STREAM,0);
  8. //if(argc<2)
  9. //  printf("usage:IP \r\n");
  10. if(sockfd<0)
  11. printf("error exit!\r\n");
  12. bzero(&serveraddr,sizeof(struct sockaddr_in));
  13. serveraddr.sin_family=AF_INET;
  14. serveraddr.sin_port=htons(13);
  15. inet_aton("127.0.0.1",&serveraddr.sin_addr);
  16. if(argc==2){
  17. if(inet_pton(AF_INET,argv[1],&serveraddr.sin_addr)<0)
  18. printf("error trans!\r\n");
  19. }
  20. if(connect(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))<0)
  21. printf("error connect!\r\n");
  22. while((n=read(sockfd,recvline,MAXLIEN))>0)
  23. {
  24. i++;
  25. recvline[n]=0;
  26. if(fputs(recvline,stdout)==EOF)
  27. printf("fputs error!\r\n");
  28. }
  29. if(n<0)
  30. printf("error\r\n");
  31. exit 0;
  32. }

这里使用最标准的客户程序:初始化、连接、处理(和服务器使用字节流/数据报交互),里面使用的函数的作用和使用方法在后续章节都会陆续讲解。

其中最后一行的语句exit是程序退出,UNIX在一个进程终止时总是关闭该进程所有打开的描述符,我们的套接字描述符也就此关闭。

在使用read时,若果返回为0,那么说明对端已经关闭连接,如果返回值为负值,那么说明出现错误。还需要细细揣摩这句哈:TCP是一个没有边界的字节流协议。、

计算机网络各对等实体间交换的单元信心称为协议数据单元(protocol data unit PDU),分节(segment)就是对应于TCP传输层的PDU.按照协议与服务之间的关系,除了最底层物理层外,每层的PDU通过由紧邻下层提供给本层的服务接口,作为下层的服务数据单元传递给下层…………

应用层实体(如客户或服务器进程)间交换的PDU称为应用数据,其中在TCP应用进程之间交换的是没有长度限制的单个双向字节流,在UDP应用进程之间交换的是其长度不超过UDP发送缓冲区大小的单个记录,在SCTP应用进程之间交换的是没有总长度显示的单个或多个双向字节流。传输层实体(对应某个端口的传输层协议代码的一次运行)间交换的PDU称为消息,其中TCP的PDU特称为分节。消息或分节的长度是由限的。在TCP传输层中,发送端TCP把来自应用进程的字节流数据(既由应用进程通过一次输出操作写出到发送端TCP套接字中的数据)按顺序经分割后封装在各个各个分节中传送给接受端TCP其中每个分节所封装的数据既可能是发送端应用进程单词操作的结果,也可能是连续数次输出操作的结果,具体取决于可在连续建立阶段由对端通告的最大分节大小(maximum segmen size MSS)以及外出接口的最大传输单元(maximumtransmission unit MTU)或外出路经的路径MTU(如果网络层具有路径MTU发现功能)。分节除了用于承载应用数据外,也用于建立连接(SYN分节)、终止连接(FIN分节)、中止连接(RST分节)、确认数据接收(ACK分节)刷送待发数据(PSH分节)和携带紧急数据指针(URG分节),而且这些功能(包括承载数据)可以灵活组合。UDP传输层相当简单,发送端UDP就把俩字应用进程的单个记录整个封装在UDP消息中传送给接受端UDP。SCTP引入了称为块的数据单元,SCTP消息就由一个公共首部加上一个或多个块构成,公共首部类似UDP消息的首部,仅仅给出源目的端口和整个SCTP消息的校验和,块则可既可以承载数据,也可以承载控制信息。

网络层实体间的PDU称为IP数据报(IPdatagram),其长度有限:Ipv4数据报最大65535字节,Ipv6数据报最大65575字节。发送端IP把来自传输层的消息(或TCP分节)整个封装在IP数据报中发送。链路层实体间交换的PDU称为帧,其长度取决于具体的接口。IP数据报由IP首部和所承载的传输层数据(既网络层的SDU,由上面的定义可以看出来,上层的PDU也就是下层的SDU,所以这里也可认为是传输层传递的消息或者分节)构成。过长的IP数据报无法封装在单个帧中,需要先对其SDU进行分片,再把分成的各个片段冠以新的IP首部封装到多个帧中。在一个IP数据报从源到目的端的传送过程中,分片操作既可能发生在源端,也可能发生在途中,而其逆操作为重组。

TCP/IP协议簇为提高效率会尽可能避免IP的分片/重组操作,TCP根据MSS和MTU限定每个分节的大小以及SCTP根据MTU分片/重组过长记录都是这个目的。无论是否分片,都由IP作为链路层的SDU传输链路层,并由链路层封装在帧中的数据称为分组(俗称包)可见一个分组既可能是一个完整的IP数据报,也可能是某个IP数据报的SDU的一个片段被冠以新的IP首部后的结果。文中讨论的MSS是应用层(TCP)与传输层之间的接口属性,MTU则是网络层和链路层之间的接口属性。

三、一个简单的时间获取服务器程序

[cpp] view plain copy

  1. #define MAXLIEN 1024
  2. int main(int argc,char *argv[])
  3. {
  4. int i,sockfd,n,connfd;
  5. time_t ticks;
  6. struct sockaddr_in serveraddr;
  7. char recvline[MAXLIEN+1];
  8. sockfd=socket(AF_INET,SOCK_STREAM,0);
  9. //if(argc<2)
  10. //  printf("usage:IP \r\n");
  11. if(sockfd<0)
  12. printf("error exit!\r\n");
  13. bzero(&serveraddr,sizeof(struct sockaddr_in));
  14. serveraddr.sin_family=AF_INET;
  15. serveraddr.sin_port=htons(13);
  16. serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
  17. bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
  18. listen(sockfd,4);
  19. //if(inet_pton(AF_INET,argv[1],&serveraddr.sin_addr)<=0)
  20. //  printf("error trans!\r\n");
  21. for(;;)
  22. {
  23. connfd=accept(sockfd,NULL,NULL);
  24. ticks=time(NULL);
  25. snprintf(recvline,sizeof(recvline),"%.24s\r\n",ctime(&ticks));
  26. write(connfd,recvline,strlen(recvline));
  27. close(connfd);
  28. }
  29. return 0;
  30. }

遵循了服务器程序的流程:初始化、绑定、监听、接受、处理(和客户进行交互)
程序中的函数在后续章节有讲解。

四、OSI模型

网络层由IPv4和IPv6这两个协议处理,可以选择的传输层有TCP或UDP,在上图中TCP与UDP之间留有间隙,表明网络应用绕过传输层直接使用IPv4或IPv6是可能的,这就是所谓的原始套接字。

OSI模型的顶上三层被合并成一层,称为应用层。这就是web客户(浏览器)、telnet客户、web服务器、ftp服务器和其其他我们在使用的网络应用所在的层。对于网际协议,OSI模型的顶上三层协议几乎没有区别。

在这一系列的讲述中,套接字编程接口是从顶上三层(网际协议的应用层)进入传输层的接口。所有文章的焦点是:如何使用套接字编写使用TCP或UDP的网络应用程序。

五、介绍几个命令

1)  netstat  netstat –i提供网络接口的信息。我们还指定-n标志以输出数值地址,而不是试图把他们反响解析成名字。

2)  netstat –r 展示路由表

这一章中主要讲解了和基本的信息,从宏观上讲解了本书的大体框架

ps:

UNIX系统中程序和进程是在系统调用上exec上衔接的。exec既可以由shell隐式调用(直接在shell输入命令执行程序属于这种情况),也可以在用户程序中显示调用。

从上层到下层的PDU(协议数据单元)的名字为:应用数据,消息/分节(TCP协议特有的)、帧、分组(俗称包)

关于UNIX中的errno的值:

只要一个UNIX函数(例如某个套接字函数)中有错误发生,全局变量errno就被置为一个指明错误类型的正直,函数本身则通过返回-1.err_sys查看errno变量的值并输出响应的出错消息,例如errno=ETIMEDOUT,输出为“Connection timed out”

在全局变量中存放errno值对于共享所有全局变量的多个线程并不合适,在26章有讲解

如果想要了解红字及其下面的部分就需要看作者的另外一本书了:TCP/IP详解

转载请标明出处

时间: 2024-10-13 00:33:07

UNIX网络编程--简介(一)【转】的相关文章

Unix网络编程 之 socket简介

概述 Socket的英文原意是"孔"或"插座",现在,作为Unix的进程通信机制,常常取"插座"这一意义.日常生活中常见的插座,有的是信号插座,有的是电源插座,有的可以接收信号或能量,有的可以发送信号或能量.举例来说,电话线与电话机之间需要一个插座(相当于两者之间的接口,这一部分装置物理上是存在的).对于网络编程,socket就相当于电话线与电话机之间的插座. 将电话系统与面向连接的Socket机制相比,两者之间有着惊人的相似的地方.以一个国家的

UNIX网络编程笔记(2)—套接字编程简介

套接字编程概述 说到网络编程一定都离不开套接字,以前用起来的时候大多靠记下来它的用法,这一次希望能理解一些更底层的东西,当然这些都是网络编程的基础- (1)套接字地址结构 大多说套接字函数都需要一个指向套接字地址结构的指针作为参数,每个协议族都定义它自己的套接字地址结构,这些结构都以sockadd_开头. IPV4套接字地址结构 IPv4套接字地址结构通常称为"网际套接字地址结构",以sockaddr_in命名,并定义在 /* Internet address. */ typedef

Unix网络编程--卷一:套接字联网API 读书笔记

UNIX网络编程--卷一:套接字联网API 本书面对的读者是那些希望自己编写的程序能够使用成为套接字(socket)的API进行彼此通信的人. 目录: 1.简介 2.传输层:TCP.UDP和SCTP 3.套接字编程简介 4.基本TCP套接字编程 5.TCP客户/服务器程序例子 6.I/O复用:select和poll函数 7.套接字选项 8.基本UDP套接字编程 9.基本SCTP套接字编程 10.SCTP客户/服务器程序例子 11.名字与地址转换 12.IPV4与IPV6互操作性 13.守护进程和

[转载] 读《UNIX网络编程 卷1:套接字联网API》

原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网络编程 卷1:套接字联网API>, 英文名叫Unix Network Programming啦,后来上网查了查, 一般都叫UNP逼格会高一点, 就像APUE一样. 他们的作者都是W. Richard Stevens. 另外,他也是TCP/IP Illustrated的作者. 靠,看完作者简介,简直崇拜得

unix网络编程之基本套接口编程

第一章  套接口编程简介 IPv4套接口地址:"网际套接口地址结构" 通用套接口地址结构: 套接口函数被定义为采用指向通用套接口地址结构的指针,这要求对这些函数的任何调用都必须将指向特定于协议的套接口地址结构的指针类型转换成指向通用套接口地址结构的指针: 套接口地址结构的比较: 值-结果参数: 当把套接口地址结构传递给套接口函数时,总是通过指针来传递的,即传递的是一个指向结构的指针. 1, 从进程到内核传递套接口地址结构有3个函数:bind.connect.sendto,这3个函数的一

UNIX网络编程笔记(1)—传输层协议

开始学习网络编程的经典<UNIX网络编程>(第3版)作为研究生阶段的副本练习吧,厚厚一本书,希望能坚持看下去,坚持做些笔记. 1.TCP/IP协议概述 IPv4 网际协议版本4(Internet Protocol version 4),32位地址,为TCP.UDP.SCTP.ICMP和IGMP提供分组递送服务. IPv6 网际协议版本6(Internet Protocol version 6).128位地址,为TCP.UDP.SCTP和ICMPv6提供分组递送服务. TCP 传输控制协议(Tr

UNIX网络编程 卷1:套接字联网API

这篇是计算机类的优质预售推荐>>>><UNIX网络编程 卷1:套接字联网API> UNIX和网络专家W. Richard Stevens的传世之作,世界著名网络专家Bill Fenner和Andrew M. Rudoff执笔新版 编辑推荐 这是一部传世之作!顶级网络编程专家Bill Fenner和Andrew M. Rudoff应邀执笔,对W. Richard Stevens的经典作品进行修订.书中吸纳了近几年网络技术的发展,增添了IPv6.SCTP协议和密钥管理套接字

UNIX网络编程入门——TCP客户/服务器程序详解

前言 最近刚开始看APUE和UNP来学习socket套接字编程,因为网络这方面我还没接触过,要等到下学期才上计算机网络这门课,所以我就找了本教材啃了一两天,也算是入了个门. 至于APUE和UNP这两本书,书是好书,网上也说这书是给进入unix网络编程领域初学者的圣经,这个不可置否,但这个初学者,我认为指的是接受过完整计算机本科教育的研究生初学者,需要具有完整计算机系统,体系结构,网络基础知识.基础没打好就上来啃书反而会适得其反,不过对于我来说也没什么关系,因为基础课也都上得差不多了,而且如果书读

UNIX网络编程卷1 回射客户程序 TCP客户程序设计范式

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 下面我会介绍同一个使用 TCP 协议的客户端程序的几个不同版本,分别是停等版本.select 加阻塞式 I/O 版本. 非阻塞式 I/O 版本.fork 版本.线程化版本.它们都由同一个 main 函数调用来实现同一个功能,即回射程序客户端. 它从标准输入读入一行文本,写到服务器上,读取服务器对该行的回射,并把回射行写到标准输出上. 其中,非阻塞式 I/O 版本是所有版本中执行速度最快的,