通常说函数返回某个错误值,实际上是函数返回值为-1,而全局变量errno被置为指定的常值(即称函数返回这个错误值)。

exit终止进程,Unix在一个进程终止时总是关闭该进程所有打开的描述符。

TCP三次握手完毕,accept返回,其返回值是一个称为已连接描述符(connected descriptor)的新描述符。调用close关闭与客户的连接。

套接字API

TCP状态转移图,11种状态。

MSS,maximum segment size,最大分节大小。通常客户端主动打开时发送SYN的同时会发送MSS,服务端应答(SYN、ACK、MSS)时同样也发送一个MSS,不同方向上MSS可以不同。

SCTP多宿特性,单个SCTP端点能支持多个IP地址。

SCTP的四路握手。验证标记、状态cookie。

IPv4数据报最大长度65535,包括IP首部,因为总长度字段是16位;IPv6数据报最大长度65575,包括40字节IPv6首部,因为净长度字段是16位。

IPv4首部20字节(固定长度),另外还有最多40字节可选部分。

套接字地址结构在内核和进程间传递,从进程传到内核,从内核传到进程,不是非常理解,应该就是参数传递进去和被写回吧?另外有一个值-结果参数以前很少碰到。

每个文件或套接字都有一个引用计数,引用计数在文件表项中维护。

存放在硬盘上的可执行程序文件能被Unix执行的唯一方法是:由一个现有进程调用六个exec函数中的一个。(理解)

六个exec函数区别在于:待执行程序由文件名还是路径名指定;参数是一一列出还是指针数组;把调用进程环境传递给新程序还是指定新环境。

子进程调用exec时,子进程内存映像被替换成新程序文件,只有文件描述符(在socket中是已连接套接字描述符)跨exec继续保持开放。

一个简单echo客户/服务器程序涉及到的一些细节(非常重要):

僵死子进程,通过捕获SIGCHLD信号加以处理;

信号处理函数必须调用waitpid而不是wait,因为unix信号是不排队的,当有多个子进程时wait函数只能处理第一个,后面的将变成僵死进程;

另一个问题是服务器进程终止时,客户进程没被告知,因为客户进程阻塞于等待用户输入而未接收到通知,这需要select或poll函数来处理,它们等待多个描述符中的任何一个就绪而不是阻塞于某个描述符。

select函数中间的三个参数(读、写、异常描述符集)都是值—结果参数,返回时,未就绪描述符对应的被置0,其他是1,重新调用时,将所关心位重置1

close函数有两个限制,shutdown函数可以克服,它关闭一半tcp连接(可参数选读或者写)。

pselect时间参数结构不同;另一个不同点是多了一个指向信号掩码的指针,从而运行程序先禁止提交某些信号。

拒绝服务(denial of service,DoS)型攻击。

UDP也可以使用connect函数,成为已连接UDP套接字,然后可以使用write和read函数读写,而不是sento和recvfrom。

DNS中的条目称为资源记录(resource record,RR)。常见RR类型有:A、AAAA、PTR、MX、CNAME。

gethostbyname和gehostbyaddr的返回值均为一个hostent(host entry缩写)结构:

  1. struct hostent {
  2. const char *h_name; // 主机的正式名称。
  3. char **h_aliases; // 空字节-地址的预备名称的指针。
  4. short h_addrtype; // 地址类型; 通常是AF_INET。
  5. short h_length; // 地址的比特长度
  6. char **h_addr_list; // 主机网络地址指针(只有IPV4)
  7. #define h_addr h_addr_list[0] // h_addr 为 h_addr_list中的第一地址。
  8. };

gethostbyname只能返回IPV4地址,而getaddrinfo能够同时处理IPV4和IPV6地址。

gethostbyname和gehostbyaddr用于主机名和地址的映射,而getservbyname和getservbyport则用于服务与端口之间的映射。

getaddrinfo能处理名字到地址、服务到端口的转换(由参数中列表中第一个为主机名,第二个为服务名可看出):

  1. int getaddrinfo( const char *hostname,
  2. const char *service,
  3. const struct addrinfo *hints,
  4. struct addrinfo **result );//返回结果保存到这里

其中,保存返回结果的struct addrinfo结构体详细信息如下:

  1. 表头文件: #include<netdb.h>
  2.  
  3. struct addrinfo
  4. {
  5. int ai_flags;
  6. int ai_family; //AF_INET,AF_INET6,UNIX etc
  7. int ai_socktype; //STREAM,DATAGRAM,RAW
  8. int ai_protocol; //IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc
  9. size_t ai_addrlen;//length of ai_addr
  10. char* ai_canonname; //full hostname
  11. struct sockaddr* ai_addr; //addr of host
  12. struct addrinfo* ai_next;
  13. }
  14.  
  15. value of ai_falgs:
  16. AI_PASSIVE: Socket address is intended for `bind'.
  17. AI_CANONNAME:Request for canonical name.
  18. AI_NUMERICHOST: Don't use name resolution.
  19. AI_V4MAPPED: IPv4 mapped addresses are acceptable.
  20. AI_ALL: Return IPv4 mapped and IPv6 addresses.
  21. AI_ADDRCONFIG:Use configuration of this host to choose
  22.  
  23. 定义函数:
  24. int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints,
  25. struct addrinfo **result );
  26.  
  27. 函数说明:
  28. getaddrinfo函数能够处理名字到地址以及服务到端口这两种转换,返回的是一个sockaddr 结构的链而 不是一个地址清单。它具有协议无关性。
  29. hostname:一个主机名或者地址串(IPv4的点分十进制串或者IPv6的16进制串)
  30. service:一个服务名或者10进制端口号数串。
  31. hints:可以是一个空指针,也可以是一个指向某个addrinfo结构的指针,调用者在这个结构中填入关于期望返回的信息类型的暗示。举例来说:如果指定的服务既支持TCP也支持UDP,那么调用者可以把hints结构中的ai_socktype成员设置成SOCK_DGRAM使得返回的仅仅是适用于数据报套接口的信息。返回0: 成功,返回非0: 出错。
  32.  
  33. 定义函数:const char *gai_strerror( int error );
  34. 函数说明:
  35. 该函数以getaddrinfo返回的非0错误值的名字和含义为他的唯一参数,返回一个指向对应的出错信息串的指针。
  36.  
  37. 定义函数: void freeaddrinfo( struct addrinfo *ai );
  38. 函数说明:
  39. 由getaddrinfo返回的所有存储空间都是动态获取的,这些存储空间必须通过调用freeaddrinfo返回给系统。

struct addrinfo结构体

与getaddrinfo函数对应的是getnameinfo函数。

  1. linux环境下,结构体struct sockaddr在/usr/include/linux/socket.h中定义,具体如下:
  2. typedef unsigned short sa_family_t;
  3. struct sockaddr {
  4. sa_family_t sa_family; /* address family, AF_xxx */
  5. char sa_data[]; /* 14 bytes of protocol address */
  6.  
  7. linux环境下,结构体struct sockaddr_in在/usr/include/netinet/in.h中定义,具体如下:
  8. /* Structure describing an Internet socket address. */
  9. struct sockaddr_in
  10. {
  11. __SOCKADDR_COMMON (sin_);
  12. in_port_t sin_port; /* Port number. */
  13. struct in_addr sin_addr; /* Internet address. */
  14.  
  15. /* Pad to size of `struct sockaddr'. */
  16. unsigned char sin_zero[sizeof (struct sockaddr) -
  17. __SOCKADDR_COMMON_SIZE -
  18. sizeof (in_port_t) -
  19. sizeof (struct in_addr)];
  20. /* 字符数组sin_zero[8]的存在是为了保证结构体struct sockaddr_in的大小和结构体struct sockaddr的大小相等 */
  21. };
  22. struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。
  23.  
  24. 下面是struct sockaddr_in中用到两个数据类型,具体定义如下:
  25. /* Type to represent a port. */
  26. typedef uint16_t in_port_t;
  27.  
  28. struct in_addr其实就是32IP地址
  29. struct in_addr {
  30. unsigned long s_addr;
  31. };
  32.  
  33. BSD网络软件中包含了两个函数,用来在二进制地址格式和点分十进制字符串格式之间相互转换,但是这两个函数仅仅支持IPv4
  34. in_addr_t inet_addr(const char *cp);
  35. char *inet_ntoa(struct in_addr in);
  36. 功能相似的两个函数同时支持IPv4IPv6
  37. const char *inet_ntop(int domain, const void *addr, char *str, socklen_t size);
  38. int inet_pton(int domain, const char *str, void *addr);
  39.  
  40. 通常的用法是:
  41. int sockfd;
  42. struct sockaddr_in my_addr;
  43. sockfd = socket(AF_INET, SOCK_STREAM, );
  44.  
  45. my_addr.sin_family = AF_INET; /* 主机字节序 */
  46. my_addr.sin_port = htons(MYPORT); /* short, 网络字节序 */
  47.  
  48. my_addr.sin_addr.s_addr = inet_addr("192.168.0.1");
  49.  
  50. bzero(&(my_addr.sin_zero), ); /* zero the rest of the struct */
  51. //memset(&my_addr.sin_zero, 0, 8);
  52.  
  53. bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
  54.  
  55. #define UNIX_PATH_MAX 108
  56.  
  57. struct sockaddr_un {
  58.  
  59. sa_family_t sun_family; /*PF_UNIX或AF_UNIX */
  60.  
  61. char sun_path[UNIX_PATH_MAX]; /* 路径名 */
  62.  
  63. };
  64.  
  65. struct sockaddr结构类型是用来保存socket信息的:
  66.    struct sockaddr {
  67.    unsigned short sa_family; /* 地址族, AF_xxx */——地址的格式
  68. char sa_data[]; /* 14 字节的协议地址 */——地址值(IP和端口号)
  69. };
  70.  
  71. Sockfd是调用socket函数返回的socket描述符,my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;addrlen常被设置为sizeof(struct sockaddr)。
  72.   struct sockaddr结构类型是用来保存socket信息的:
  73.   struct sockaddr {
  74.    unsigned short sa_family; /* 地址族, AF_xxx */
  75. char sa_data[]; /* 14 字节的协议地址 */
  76. };
  77.   sa_family一般为AF_INET,代表InternetTCP/IP)地址族;sa_data则包含该socketIP地址和端口号。
  78.   另外还有一种结构类型:
  79.   struct sockaddr_in {
  80.    short int sin_family; /* 地址族 */
  81.    unsigned short int sin_port; /* 端口号 */
  82.    struct in_addr sin_addr; /* IP地址 */
  83.    unsigned char sin_zero[]; /* 填充0 以保持与struct sockaddr同样大小 */
  84.   };
  85.    这个结构更方便使用。sin_zero用来将sockaddr_in结构填充到与struct sockaddr同样的长度,可以用bzero()或memset()函数将其置为零。指向sockaddr_in 的指针和指向sockaddr的指针可以相互转换,这意味着如果一个函数所需参数类型是sockaddr时,你可以在函数调用的时候将一个指向 sockaddr_in的指针转换为指向sockaddr的指针;或者相反。
  86.  
  87. 你只要记住,填值的时候使用sockaddr_in结构,而作为函数的
  88. 参数传入的时候转换成sockaddr结构就行了,毕竟都是16个字符
  89. 长。
  90.  
  91. struct in_addr {
  92. union {
  93. struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
  94. struct { u_short s_w1,s_w2; } S_un_w;
  95. u_long S_addr;
  96. } S_un };

struct sockaddr与struct sockaddr_in ,struct sockaddr_un的区别和联系

  1. inet_pton函数将点分十进制格式IP地址转换为二进制整数,IPV4IPV6都支持:
  1.  
  1. inet_pton:将“点分十进制” -> “二进制整数”
  2. int inet_pton(int af, const char *src, void *dst);
  3. 这个函数转换字符串到网络地址,第一个参数af是地址簇,第二个参数*src是来源地址,第三个参数* dst接收转换后的数据。
  4. inet_pton inet_addr的扩展,支持的多地址族有下列:
  5. af = AF_INET
  6. src为指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函数将该地址转换为in_addr的结构体,并复制在*dst中。
  7. af = AF_INET6
  8. src为指向IPV6的地址,函数将该地址转换为in6_addr的结构体,并复制在*dst中。
  9. 如果函数出错将返回一个负值,并将errno设置为EAFNOSUPPORT,如果参数af指定的地址族和src格式不对,函数将返回0

《Unix网络编程》卷一(简介TCP/IP、基础套接字编程)的更多相关文章

  1. 20181225 基于TCP/IP和基于UDP/IP的套接字编程

    一.TCP/IP的套接字编程 服务器端代码: import  socket​server = socket.socket() # 默认是基于TCP# 基于TCP的对象serve=socket.sock ...

  2. Java 网络编程(五) 使用TCP/IP的套接字(Socket)进行通信

    链接地址:http://www.cnblogs.com/mengdd/archive/2013/03/10/2952616.html 使用TCP/IP的套接字(Socket)进行通信 套接字Socke ...

  3. 网络编程之TCP三次握手与四次挥手、基于TCP协议的套接字编程

    目录 TCP三次握手和四次挥手 背景描述 常用的熟知端口号 TCP概述 TCP连接的建立(三次握手) TCP四次挥手 如果已建立连接,客户端突然断开,会怎么办呢? 基于TCP协议的套接字编程 什么是S ...

  4. 【Python网络编程】利用Python进行TCP、UDP套接字编程

    之前实现了Java版本的TCP和UDP套接字编程的例子,于是决定结合Python的学习做一个Python版本的套接字编程实验. 流程如下: 1.一台客户机从其标准输入(键盘)读入一行字符,并通过其套接 ...

  5. 使用TCP/IP的套接字(Socket)进行通信

    http://www.cnblogs.com/mengdd/archive/2013/03/10/2952616.html 使用TCP/IP的套接字(Socket)进行通信 套接字Socket的引入 ...

  6. TCP和UDP套接字编程 (java实现)

    在了解网络编程之前,我们先了解一下什么叫套接字 套接字即指同一台主机内应用层和运输层之间的接口 由于这个套接字是建立在网络上建立网络应用的可编程接口 因此也将套接字称为应用程序和网络之间的应用程序编程 ...

  7. 《Unix 网络编程》08:基本UDP套接字编程

    基本UDP套接字编程 系列文章导航:<Unix 网络编程>笔记 UDP 概述 流程图 recvfrom 和 sendto #include <sys/socket.h> ssi ...

  8. python 之 网络编程(基于TCP协议的套接字通信操作)

    第八章网络编程 8.1 基于TCP协议的套接字通信 服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的连 ...

  9. 【转】 VC中TCP实现 异步套接字编程的原理+代码

    所谓的异步套接字编程就是  调用了 如下函数   WSAAsyncSelect   设置了 套接字的状态为异步,有关函数我会在下面详细介绍... 异步套接字解决了 套接字编程过程中的堵塞问题 .... ...

  10. 网络编程之基于UDP协议的套接字编程、基于socketserver实现并发的socket

    目录 基于UDP协议的套接字编程 UDP套接字简单示例 服务端 客户端 基于socketserver实现并发的socket 基于TCP协议 server类 request类 继承关系 服务端 客户端1 ...

随机推荐

  1. mac终端命令大全全全全全全全全全

    OSX 的文件系统 OSX 采用的Unix文件系统,所有文件都挂在跟目录 / 下面,所以不在要有Windows 下的盘符概念. 你在桌面上看到的硬盘都挂在 /Volumes 下. 比如接上个叫做 US ...

  2. BizTalk动手实验(五)Map开发测试

    1 课程简介 通过本课程熟悉Map的相关开发与测试技术 2 准备工作 熟悉XML.XML Schema.XSLT等相关XML开发技术 新建BizTalk空项目 演示 3.1 基本操作 打开MapDev ...

  3. IOS第18天(9,核心动画-动画组)

    ****动画组 // 核心动画都是假象,不能改变layer的真实属性的值// 展示的位置和实际的位置不同.实际位置永远在最开始位置 #import "HMViewController.h&q ...

  4. A trip through the Graphics Pipeline 2011_05

    After the last post about texture samplers, we’re now back in the 3D frontend. We’re done with verte ...

  5. gdb调试,自动显示多个变量的值

    调试程序的时候有时候要一行监控多个变量的值, 可以这样写: p {var1, var2, var3} 要跟踪程序自动显示,可以使用display display {var1, var2, var3}要 ...

  6. 滚动固定TAB在顶部显示

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  7. shell读取文件每行,并执行命令

    #!/bin/bash while read line do $line & done < /path/filename

  8. 1CSS与文档

    层叠样式表(Cascading Style Sheet,CSS)的功能十分强大,可以影响一个或一组文档的表现. 为什么结构化对HTML来说很重要:1.非结构化页面使得建立内容索引极为困难.2.缺乏结构 ...

  9. 在项目里交叉使用Swift和OC【转】

    Swift and Objective-C in the Same Project在项目里交叉使用Swift和OC Swift与OC的兼容性使得你可以在项目里使用Swift+OC的方式编写应用程序,称 ...

  10. CentOS6修改主机名(hostname)及 修改/etc/hosts 文件,增加ip和hostname的映射关系(转)

    CentOS修改主机名(hostname)  需要修改两处:一处是/etc/sysconfig/network,另一处是/etc/hosts,只修改任一处会导致系统启动异常.首先切换到root用户. ...