Tcp通信
Posted yzs的专栏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tcp通信相关的知识,希望对你有一定的参考价值。
1、TCP通信过程
socket在Tcp/IP分层的哪里?
socket是应用层与Tcp/IP协议族通信中间软件抽象层,是一组接口。在设计模式中,其实就是一个门面模式,他把复杂的协议族隐藏在接口后面,对用户来说,一组简单的接口就是全部,让socket去组织数据,以符合指定的协议。
一个典型的通信过程如下图所示
工作过程:服务器端首先启动,通过调用socket函数创建一个套接字;然后调用bind函数将该套接字与一个本地地址和端口绑定在一起;接着调用listen函数将套接字设置为监听模式,准备接受用户请求;调用accept函数接收连接:等待用户请求的到来,当来时接收连接请求,返回一个新的对应于此的连接套接字;用返回的套接字和客户端进行通信,使用函数send/recv;返回,等待另一个请求的到来;最后关闭套接字。
客户端:使用socket函数创建一个套接字;使用函数connect向服务器发送连接请求;之后就可以和服务器进行通信,使用函数send/recv。
相关函数讲解:
(1)int socket(int family, int type, int protocol);
family(协议族):AF_INET:IPv4协议
AF_INET6:IPv6协议
AF_LOCAL:UNIX域协议
AF_ROUTE:路由套接字
AF_KEY:秘钥套接字
type(套接字类型):SOCK_STREAM:字节流套接字;SOCK_DGRAM:数据报套接字;SOCK_RAW:原始套接字
protocl:0原始套接字除外
返回值:成功,非负套接字描述符;出错-1
返回-1时,errno值将设为下列这些值:
- EPROTONOSUPPORT:错误原因是参数中的错误,表示申请的服务或指定的协议无效;
- EMFILE:错误的原因是应用程序的描述符已满;
- ENFILE:错误的原因是应用程序内部的系统文件表已满;
- ENOBUF:错误的原因是系统没有可用的缓冲空间
(2)绑定本地地址
int bind(int socktd, struct sockadddr *my_addr, int addrlen)
socktd: 套接字描述符;my_addr:本地地址;addrlen:地址长度
成功0,出错-1
(3)listen函数
int listen(int socktd,int backlog)
socktd:套接字描述符;backlog:请求对列中允许的最大请求数,表示在accept函数之前同时最多有多少个客户连接到这个套接字
成功0,失败-1
listen函数将一个套接字转换成监听套接字,主要做下面两件事:
socket函数建立的套接字是一个未连接的套接字,这是还不能接收内核向此套接字提供的连接请求,调用listen函数后,将这个套接字有CLOSE状态转为LISTEN状态,这时才可以准备接收内核发出的连接请求信号
由于可能会同时有很多连接请求需要处理,listen函数可以确定连接请求对列的长度。
(4)accept函数
int accept(int socktd, struct sockaddr *addr, socklen_t *addrlen)
socktd:套接字描述符;addr:客户端地址;addrlen:地址长度
函数返回值是一个套接字,程序可以用这个套接字和客户端进行通信。
(5)客户端和服务器建立连接后,可以通过函数read和write完成数据通信,但对于socket通信来说,可以用send和recv系统调用更好的进行套接字操作
int send (int socktd, const void *msg,int len, int flags)
socktd:套接字描述符,msg:指向要发送数据的指针,len:数据长度,flags一般为0;成功返回发送的字节数,否则0
int recv(int socktd, void *buf,int len, unsign int flags)
socktd:套接字描述符,buf:存放接收数据的缓冲区,len:数据的长度,flas:一般0
成功返回接收的字节数,否则0
(6)int connect(int socktd,const struct sockaddr*server_addr, socklen_t addrlen)
函数的功能是完成一个有连接协议的连接过程,对于TC P 来说就是那个三次握手过程。在建立连接的时候,总会有一方先发送数据,谁调用了connect谁就先发送数据。因此必须制定数据的发送地址,同时必须指定数据从哪里发送,这正好是前两个参数。
socktd: 套接口描述符,解决从哪里发送的问题。内核需要维护大量的IO通道,所以用户必须通过这个参数告诉内核从哪个IO通道,此处是从哪个socket接口发送数据。;
server_addr: 目标地址指针,包含IP和端口信息,也就是服务器端的地址,被连接的一方需要调用listen接收connect的连接请求,如此被动连接的一方就是服务器了;
addrlen:地址长度
以上是关于Tcp通信的主要内容,如果未能解决你的问题,请参考以下文章
【网络协议笔记】第四层:传输层(Transport)以及UPD协议简介