UNP学习笔记1——基本TCP套接字编程
1 套接字地址结构
大多数套接字函数都需要一个指向套接字地址结构的指针作为参数。每个协议族都定义了自己的套接字结构。这些套接字的结构以sockaddr_开头,以每个协议族唯一的后缀名结尾。
1.1 IPV4套接字地址结构
IPV4套接字结构通常被称为网际套接字结构,以sockaddr_in命名,定义在<netinet/in.h>头文件中。
struct sockaddr_in { uint8_t sin_len; //数据结构长度(16)
sa_family_t sin_family; //AF_INET in_port_t sin_port; //16位TCP或UDP端口号,采用网络字节序
struct in_addr sin_addr; //32位IPV4地址,采用网络字节序
char sin_zero[]; //保留
}; struct in_addr { in_addr_t s_addr; //32位IPV4地址,采用网络字节序
};
- POSIX规范只需要sin_family、sin_addr和sin_port三个字段。
- 长度字段sin_len是为了增加对OSI协议的支持才添加的,有了长度字段可以简化长度可变套接字地址结构的处理。除非涉及路由套接字,平时我们无需设置和检查它。
- IPV4地址和TCP/UDP端口号在套接字地址结构中都是以网络字节序来存储。
- 32位IPV4地址有两种不同的访问方法:server.sin_addr将以in_addr结构引用其中32位IPV4地址;而server.sin_addr.s_addr将以in_addr_t(通常是一个32位无符号整数)引用一个32位IPV4地址。因此应当正确使用IPV4地址,尤其是在函数引用时。因为编译器对传递结构和传递整数的处理是完全不同的。
- sin_zero字段未使用,置为0
- 套接字地址结构仅在本机上使用,结构本身并不在主机之间传递。
1.2 通用套接字地址结构
套接字的地址结构总是以引用(即指向该结构的指针)的形式传给套接字函数因此需要一个通用的套接字地址结构来处理任何协议族的情况。
#include <sys/socket.h> struct sockaddr { uint8_t sa_len;
sa_family_t sa_family; //地址族:AF_XXX
char sa_data[]; //特定协议定义的地址类型
};
这些通用套接字地址结构的唯一作用就是对指向特定协议的套接字地址结构指针进行强制类型转换。
1.3 IPV6套接字地址结构
#include <netinet/in.h> struct in6_addr { uint8_t s6_addr[]; //128位IPV6地址,采用网络字节序
}; #define SIN6_LEN //required foe compile-time tests
struct sockaddr_in6 { uint8_t sin6_len; //该结构长度(28)
sa_family_t sin6_family; //AF_INET6
in_port_t sin6_port; //transport layer port#,采用网络字节序 uint32_t sin6_flowinfo; //流信息,未定义
struct in6_addr sin6_addr; //IPV6地址,采用网络字节序 uint32_t sin6_scope_id; //set of interfaces for a scope
};
- 如果系统支持套接字地址结构中的长度字段,那么常值SIN6_LEN必须被定义
- IPV6地址族为AF_INET6,IPV4地址族为AF_INET
- 结构中字段的先后顺序经过编排,保证64位对齐
- sin6_flowinfo字段分成两个字段:低序20位是流标(flow label),高序12位保留
- 对于具备范围的地址(scoped address),sin6_scope_id标识其范围(scope),最常见的是链路局部地址的接口索引
1.4 套接字地址结构的比较
1.5 字节序函数
网络协议使用大端字节序来传输多字节字段。
大端字节序和小端字节序的转换函数如下:
#include <netinet/in.h> /*主机字节序转网络字节序*/
uint16_t htons(uint16_t host16value);
uint32_t htonl(uint32_t host32value); /*网络字节序转主机字节序*/
uint16_t ntohs(uint16_t net16value);
uint32_t ntohl(uint32_t net32value);
函数名字中,h代表host,n代表network,s代表short,l代表long。
1.6 字节操纵函数
#include <strings.h> void bzero(void *dest, size_t nbytes); //把目标字节串中指定数目的字节置为0
void bcopy(const void *src, void *dest, size_t nbytes); //指定数目的字节拷贝
int bcmp(const void *ptr1, const void *ptr2, size_t nbytes); /*返回:相等则为0,否则为非0*/ void *memset(void *dest, int c, size_t len); //把目标字节串指定数目的字节置为值c
void *memcpy(void *dest, const void *src, size_t nbytes); //类似bcopy,不过两个指针参数的顺序是相反的
int memcmp(const void *ptr1, const void *ptr2, size_t nbytes); /*返回:相等为0,否则<0或>0*/
memcpy类似bcpy,不过两个指针参数的顺序是反的,memcpy遵循C语言的赋值顺序:dest=src。但是当源字节串与目标字节串重叠时,bcpy能正确处理,但是memcpy的结果不可知。
memcmp比较两个字节串,相等返回0,不等返回非0,是大于0还是小于0取决于第一个不等的字节。
1.7 地址转换函数
下面两个函数用于IPV4地址在点分十进制和32位网络字节序之间转换:
#include <arpa/inet.h> int inet_aton(const char *strptr, struct in_addr *addrptr); /*返回:若字符串有效则为1,否则为0*/
char *inet_ntoa(struct in_addr *inaddr); /*返回:一个点分十进制字符串的指针*/
下面两个新函数,对于IPV4和IPV6都适用:
#include <arpa/inet.h> int inet_pton(int family, const char *strptr, void *addrptr); /*返回:成功为1,若输入不是有效的表达格式则为0,出错则为-1*/
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len); /*返回:成功则返回指向结果的指针,出错则为NULL*/
这两个函数的参数family可以是AF_INET或AF_INET6
inet_pton函数尝试转换由strptr指向的字符串,并通过addrptr指针存放二进制结果。inet_ntop进行相反的转换,len参数是目标存储单元的大小,以免该函数溢出调用者的缓冲区。如果len太小不能完整存放结果,则返回一个空指针,并置errno为ENOSPEC。
inet_ntop函数的strptr参数不能为空指针。调用者必须为目标存储单元分配内存并指定其大小。调用成功时,这个指针就是该函数的返回值。
2 基本TCP套接字编程
本章讲解一个完整的TCP客户/服务器程序所需要的基本套接字函数。
2.1 socket函数
#include <sys/socket.h> int socket (int family, int type, int protocol); /*返回:成功返回非负描述符,出错-1*/
其中,family表示协议族,包括AF_INET、AF_INET6、AF_LOCAL(Unix域协议)、AF_ROUTE(路由套接字)、AF_KEY(密钥套接字),该参数也往往被称为协议域。type参数指明套接字类型,包括SOCK_STREAM(字节流套接字)、SOCK_DGRAM(数据报套接字)、SOCK_SEQPACKET(有序分组套接字)、SOCK_RAW(原始套接字)。protocol参数应设为某个协议类型常值,或者设为0,以选择所给定的family和type组合系统默认参数值。
socket函数在成功后返回一个小的非负整数值,它与文件描述符类似,称为套接字描述符,简称sockfd。为了得到这个套接字描述符,我们制定了协议族和套接字类型,但是并没有指定本地协议地址或远程协议地址。
2.2 connect函数
TCP客户端用connect函数来建立与TCP服务器的连接。
#include<sys/socket.h> int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen); /*返回:成功为0,出错为-1*/
第二个和第三个参数分别指向一个套接字地址结构指针和该结构的大小。
客户端在调用connect函数之前不用必须调用bind函数,因为内核会确定源IP地址,并选择一个临时端口作为源端口。
若是TCP套接字,调用connect函数将激发TCP的三路握手过程,而且仅在建立成功或出错之后才返回,其中出错返回可能有以下几种情况:
- TCP客户端没有收到SYN分节的响应,则返回ETIMEOUT错误。
- 若服务器对客户SYN的响应是RST(复位),则表明服务器在该端口上没有进程在等待连接(或者服务器主动取消连接),这是一种硬错误,返回ECONNREFUSED错误。
- 若客户端在发送SYN路径上某个路由器上引发了一个路径不可达的ICMP错误,这是一种软错误。客户端进程保存该信息,并在固定间隔内重复发送SYN,达到规定时间之后则返回EHOSTUNREACH或ENETUNREACH错误。
2.3 bind函数
bind函数把一个本地协议地址赋予一个套接字。
#include <sys/socket.h> int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); /*返回:成功为0,出错为-1*/
第二个和第三个参数分别指向一个套接字地址结构指针和该结构的大小。对于TCP,调用bind函数可以指定一个端口号,或者指定一个IP地址,也可以两者都指定或者都不指定。服务器在启动时捆绑它们的众所周知接口,进程可以把一个特定的IP地址绑定到它的套接字上,不过这个IP地址必须属于其所在主机的网络接口之一。
2.4 listen函数
listen函数仅由TCP服务器调用,它做两件事情:
- 当socket函数创建一个套接字时,它被假设为一个主动套接字,也就是说默认是一个主动发起connect的套接字。listen函数将一个未连接的套接字转换成一个被动套接字,指示内核应该接受指向该套接字的连接请求。
- 函数第二个参数规定了内核应该为相应套接字的最大连接个数。
#include <sys/socket.h> int listen(int sockfd, int backlog); /*返回:若成功返回0,出错为-1*/
对于理解backlog函数,必须认识到内核为任何一个监听的套接字维护两个队列:
- 未完成连接队列:服务器收到客户端的SYN,等待完成三次握手过程,此时套接字处于SYN_RCVD状态。
- 已完成连接队列:已完成三次握手,套接字出ESTABLISHED状态。
- 两个队列之和不得超过backlog。
2.5 accept函数
#include <sys/socket.h> int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen); /*成功返回非负描述符,出错返回-1*/
accept函数由TCP服务器调用,用于从已完成连接队列对头返回下一个已完成的连接。如果已完成的队列为空,那么进程就被投入休眠(假定套接字为默认阻塞模式)。
参数cliaddr和addrlen用来返回已连接的客户端的协议地址。addrlen是值-结果参数;调用前,我们将由*addrlen所指向的整数置为*cliaddr所指向的套接字结构的长度,返回时,该整数值有内核存放在该套接字地址结构的确切字节数。
如果accept成功,其返回一个内核生成的全新套接字描述符,成为已连接套接字描述符。而accept函数的第一个参数成为监听套接字描述符。一个服务器通常只创建一个监听套接字,它在服务器程序运行周期内一直存在。而当服务器完成对客户的服务时,其对应的已连接套接字就会被关闭。
2.6 close函数
#include <unistd.h>
int close(int sockfd);
/*返回:成功则为0,出错则为-1*/
close一个套接字的默认行为是将它标记为已关闭状态,然后立即返回到调用进程,之后该进程就不能再使用这个套接字描述符了。而TCP之后会尝试发送已排队等待的,将要发送到对端的数据,发送完毕之后发生的是正常的TCP连接终止序列。
UNP学习笔记1——基本TCP套接字编程的更多相关文章
- UNP学习笔记3——基本UDP套接字编程
1 概述 TCP和UDP网络编程存在一些本质的差异,主要是由于传输层的差别:UDP是无连接的不可靠的数据报协议,而TCP是面向连接的字节流协议. 下图是典型的UDP客户端和服务器之间的通信流程.客户不 ...
- UNP——第四章,TCP套接字编程
1.socket 函数 首先被调用的函数,用于选择通信协议. socket调用成功后,得到的套接字为主动套接字CLOSED状态. PF 和 AF 的关系 PF的是协议族,AF是地址族,理论上一个PF包 ...
- TCP套接字编程模型及实例
摘要: 本文讲述了TCP套接字编程模块,包括服务器端的创建套接字.绑定.监听.接受.读/写.终止连接,客户端的创建套接字.连接.读/写.终止连接.先给出实例,进而结合代码分析. PS:本文权当 ...
- 【UNIX网络编程(四)】TCP套接字编程具体分析
引言: 套接字编程事实上跟进程间通信有一定的相似性,可能也正由于此.stevens这位大神才会将套接字编程与进程间的通信都归为"网络编程",并分别写成了两本书<UNP1> ...
- 套接字编程相关函数(2:TCP套接字编程相关函数)
本文摘录自<UNIX网络编程 卷1>. 基本套接字函数 socket函数 为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型.其定义如下: #in ...
- unix网络编程第四章----基于TCP套接字编程
为了执行网络I/O操作.进程必须做的第一件事情就是调用Socket函数.指定期待的通信协议 #include<sys/socket.h> int socket(int family,int ...
- 初探网络编程--TCP套接字编程演示
今天看了一下<计算机网络:自顶向下方法>,也就是计算机网络的教材的应用层一章,决定实现以下后面的Java C/S应用程序的例子,用来演示TCP和UDP套接字编程. 程序流程如下: 1.一台 ...
- TCP套接字编程
一.套接字(socket)函数 图1给出了在一个TCP客户与服务器通信的流程.服务器首先启动,稍后某个客户启动,它试图连接到服务器.假设客户给服务器发送一个请求,服务器处理该请求,并且给客户发回一个相 ...
- 【UNIX网络编程(二)】基本TCP套接字编程函数
基于TCP客户/server程序的套接字函数图例如以下: 运行网络I/O.一个进程必须做的第一件事就是调用socket函数.指定期望的通信协议类型. #include <sys/socket.h ...
随机推荐
- 使用jQuery和CSS自定义HTML5 Video 控件 简单适用
Html5 Video是现在html5最流行的功能之一,得到了大多数最新版本的浏览器支持.包括IE9,也是如此.不同的浏览器提供了不同的原生态浏览器视频空间.我们制作自定义视频控件为了在所有的浏览器中 ...
- C++继承与组合
转自https://blog.csdn.net/caoyan_12727/article/details/52337297 类的组合和继承一样,是软件重用的重要方式.组合和继承都是有效地利用已有类的资 ...
- nyoj27-水池数目【DFS】
题目描述: 南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地图上仅标识了此处是否是水池,现在,你的任务来了,请用计算机算出该地图中共有几个水 ...
- 洛谷P1046 陶陶摘苹果
题目描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 101010 个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个 303030 厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳 ...
- 设置ssh会话过期时间
客户端配置选项: 编辑配置文件 ~/.ssh/config 加入以下配置项,如不存在新建一个即可: Host * ServerAliveInterval 300 ServerAliveCountMax ...
- Oracle数据库性能优化基础
1.数据处理分类OLTP,OLAP 2.Oracle特性 3.数据库优化方法论/原则 方法论:自顶向下优化和自底向上优化 3.1 自顶向下优化 3.2 自底向上优化 对于多年的老系统出现性能问题时,就 ...
- Maven Hibernate
1.使用maven管理Hibernate实现自动装配jar包 2.需要在配置文件pom.xml中引入 如:引入hibaernate5.2.11.Final版本的jar包,需要做如下配置: <!- ...
- Java 微信公众号上传永久素材的方法
Java 微信公众号上传永久素材的方法 学习了:http://blog.csdn.net/u013791374/article/details/53258275 膜拜一下,源码如下: @Request ...
- HorizontalDragLayout-模仿QQclient的Item滑动删除
首先感谢http://blog.csdn.net/lmj623565791/article/details/46858663hongyang的文章.之前看过ViewDragHelper类也读过一些de ...
- ASP.Net MVC – What are the uses of Display, DisplayName, DisplayFormat and ScaffoldColumn attributes
http://www.codeproject.com/Articles/775220/ASP-Net-MVC-What-are-the-uses-of-Display-DisplayNa?utm_so ...