概述
言之者无罪,闻之者足以戒。 - “诗序”
TCP通信也就是服务器和客户端的一种通信方式,它的整体框架为:
针对TCP通信所用到的函数,我来做一下说明:
(1)插座创造一个套接字
int socket(int domain,int type,int protocol)
头文件的:#include <SYS / socket.h>中
第一个参数:通信域,确定通信特性,包括地址格式域描述
第二个参数:套接字类型
第三个参数:指定相应的传输协议
返回值:成功则返回套接字文件描述符,失败返回-1
参数域:通信域,确定通信特性,包括地址格式域描述
参数协议:指定相应的传输协议,也就是诸如TCP或UDP协议等等,系统针对每一个协议簇与类型提供了一个默认的协议,我们通过把协议设置为0来使用这个默认的值。
family: | type: | 组合 | AF_INET | AF_INET6 | AF_LOCAL | AF_PACKET | |||
簇 | 解释 | SOCK_STREAM | 字节 流套接字 | TCP | TCP | YES | |||
AF_INET | IPv4协议 | SOCK_DGRAM | 数据包套接字 | UDP | UDP | YES | |||
AF_INET6 | IPv6协议 | SOCK_RAM | 原始套接字 | IPv4 | IPv6 | ethernet | |||
AF_LOCAL/AF_UNIX | 本地套接字 | ||||||||
AF_PACKET |
(2)建立与TCP服务器的连接
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen)
第一个参数:是由socket函数返回的套接字描述符
第二个参数:指向套接字地址结构的指针
第三个参数:地址结构的大小
套接字地址结构必须包含有服务器的IP地址和端口号
返回值:成功返回0,出错返回-1
客户在调用connect之前不必非得调用bind函数,因为如果需要的话,内核会确定源IP地址并选择一个临时端口作为端口号
如果是TCP套接字,调用connect函数将激发TCP的三次握手过程,而且仅在连接建立成功或出错时才返回,其中,出错返回的可能情况有以下几种:
1)若TCP客户没有收到SYN分节的响应,则返回ETIMEDOUT错误。举例,调用connect函数时,4.4BSD内核发送一个SYN,若无响应则等待6s后再发送一个,若仍无响应则等待24s后再发送一个。若总共等待了75s后仍未收到响应则返回本错误
2)若对客户的SYN的响应是RST(表示复位),则表明该服务器主机在我们指定的端口上没有进程在等待与之连接。这是一种硬错误,客户一收到RST就马上返回ECONNREFUSED错误。
3)若客户发出的SYN在中间的某个路由器上引发了一个“destination unreachable”(目的地不可达)ICMP错误,则认为是一个软错误。客户主机内核保存该消息,并按第一种情况所述的时间间隔继续发送SYN。若在某个规定的时间内仍无响应,则把保存的信息(即ICMP错误)作为EHOSTUNREACH或ENETUNREACH错误返回给进程。以下两种情况是有可能的:一是按照本地系统的转发表,根本没有到达远程系统的路径;二是connect调用根本不等待就返回。
(3)结合绑定服务器的地址和端口到插座
这样做就是让客户端来发现用以连接的服务器的地址
int bind(int sockfd,const struct sockaddr * addr,socklen_t len)
头文件:#include <sys / socket.h>
第一个参数:是由socket函数返回的套接字描述符
第二个参数:服务器的地址
第三个参数:地址的长度
返回值:成功返回0,失败返回-1
参数地址:服务器的地址,对于因特网域,如果设置地址为INADDR_ANY,套接字可以绑定到所有的网络端口。这意味着可以收到这个系统所有网卡的数据包。一般我们,在使用SOCKADDR_IN类型的结构体代替的sockaddr行业释义体系结构
参数len:指定地址的长度
下面罗列一下常见的几种出错情况:
1)IP地址可以选择通配地址,端口号为0表示(内核分配临时端口)
2)INADDR_ANY,由内核选择IP接口,这个宏的值为0(注意:该宏对于IPv4是可行的)
3)分配临时端口号,需要用函数getsockname,来返回 你的协议地址
4)绑定通常会返回的错误:Address already in use ,通过套接字选项来设置,setsockopt,SO_REUSEADDR
(4)设置允许的最大连接数
int listen(int sockfd,int backlog)
头文件:#include <sys / socket.h>
第一个参数:是由socket函数返回的套接字描述符
第二个参数:用于表示服务器能接受的请求数量
返回值:成功返回0,失败返回-1
服务器调用监听函数来宣告可以接受连接请求
关于listen函数的相关内容可以参考https://www.cnblogs.com/lengender-12/p/6813057.html
(5)接受等待来自客户端的连接请求
int accept(int sockfd,struct sockaddr * restrict addr,socklen_t * restrict len)
头文件的:#include <SYS / socket.h>中
第一个参数:是由socket函数返回的套接字描述符
第二个参数:用来存放客户端的地址,如果地址的空间足够大,系统会自动填充。
第三个参数:地址的长度
返回值:成功则返回套接字描述符,失败返回-1
一旦服务器调用了听,套接字就能接收连接请求。使用接受函数来接受并建立请求
注意:
1,接受返回一个新的socket关联到客户端,它与原始的socket有相同的套接字类型和协议族。传递给接受的原始socket并没有关联客户端,它要继续保持可用状态,接收其他请求。
2,接受是一个阻塞的函数,会一直等到有客户端的请求。
最后
以上就是典雅小懒猪为你收集整理的Linux学习之网络编程(TCP编程 模型总结)的全部内容,希望文章能够帮你解决Linux学习之网络编程(TCP编程 模型总结)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复