资源描述
一、 TCP/IP、UDP的基本概念
TCP/IP即传输控制协议,是一个工业标准协议集,为广域网设计的。涉及多个其他协议,主要以TCP和IP为代表。UDP即用户数据报协议。
TCP/IP进行数据传输主要分为两个过程:建立连接过程和数据传输过程。
TCP/IP协议通过三次握手建立一个可靠的连接,步骤:
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
数据传输过程:
发送端发送数据,然后进入等待ACK确定信号状态,随后接收端接收到数据,发送ACK确认信号,发送端接收到ACK后才发送下一组数据,同时发送端有一个定时器,定时时间到了没有接收到ACK,就认为发送失败了,进行重新发送。因为发送端发送完数据后处于等待状态,因此为了提高效率,引入“滑动窗口”的概念,就是发送的时候一次发送多组数据,相当于窗口的大小,然后当接收到第一个ACK后,就将窗口向后移动一个数据,就形成了滑动窗口的情况。
二、Socket编程
1创建套接口:
Int socket(int family,int type,int ptotocol)
功能:生成一个套接口描述
返回值:成功返回套接口描述符,失败返回-1.
参数1:family指明协议族
PF_UNIX----UNIX协议族
PF_INET-----IPV4协议
PF_INET6---IPV6协议
AF_ROUTE—路由套接口
参数2:type指明通信字节流,取值
SOCK_STREM----TCP方式
SOCK_DGRAM---UDP方式
SOCK_RAW------原始套接口
参数3:ptotocol一般设置为0
2绑定端口:
Int bind(int sockfd,const struct sockaddr * my_addr,socklen addrlen)
功能:调用socket创建一个套接口后,需要使用bind函数在这个套接口上绑定一个指定的端口号和IP地址。
返回:成功0,失败-1
参数1:sockfd已建立的socket编号(描述符)
参数2:my_addr是一个指向sockaddr结构体类型的指针
参数3:addrlen表示my_addr结构的长度,可以用sizeof获得
3等待监听函数
Int listen(int sockfd,int backlog)
功能:监听是指socket的端口一直处于等待的状态,监听网络中的所有客户机,耐心等待某一客户机的发送请求。如果客户端有连接请求,端口就会接受这个链接。
返回:成功0,失败-1
参数1:sockfd已建立的套接口描述符
参数2:backlog能同时处理的最大连接请求数,如果超过这个数目,客户端将接收到ECONNREFUSED拒绝连接的错误
4接受连接的函数
Int accept(int sockfd,struct sockaddr *addr,socketlen *addrlen)
功能:服务区处于监听状态,若某时获得客户机的连接请求,此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统空闲时在处理客户机的连接请求,接受连接请求的函数式accept。
返回:成功返回新的套接口描述符 ,失败-1
参数1:sockfd表示处于监听状态的socket
参数2:addr是一个sockaddr结构体类型的指针,系统会把远程主机的信息保存到这个指针所指向的结构体中。
参数3:addrlen表示sockaddr的内存长度,可以用sizeof函数取得。
当accept函数接受一个连接时,会返回一个新的socket标示符,以后的数据传输与读取就是通过这个新的socket编号来处理,原来参数中的socket也可以继续使用。接受链接以后,远程主机的地址和端口信息将会保存到addr所指的结构体中。
5请求连接的函数
Int connect(int sockfd,const struct sockaddr *serv_addr,int addrlen)
功能:客户机向服务器发送信息之前,需要先发送一个链接请求,请求与服务器建立一个连接请求,请求与服务器建立TCP通信连接。Connect函数会将本地的socket连接到serv_addr所指定的服务器IP与端口号上去。
返回:成功0,失败-1
参数1:sockfd表示已建立的套接口标示符。
参数2:serv_addr是一个结构体指针,指向一个sockaddr结构体,这个结构体存储着远程服务器的IP与端口号信息
参数3:addrlen表示sockaddr结构体的内存长度,可以用sizeof取得
6数据发送函数 TCP使用
int send(int socket,const void*msg,int len,unsigned int flags );
功能:不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。
返回:成功返回已发送的字符数,失败-1
参数1:socket指定发送端套接字描述符;
参数2:msg指明一个存放应用程序要发送数据的缓冲区即需要发送数据的指针;
参数3:len指明实际要发送的数据的字节数;
参数4:flags一般置0。
这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字socket的发送缓冲的长度,如果len大于socket的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于socket的发送缓冲区的长度,那么send先检查协议 是否正在发送socket的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送socket的发送缓冲中的数据或者socket的发送缓冲中没有数据,那么 send就比较socket的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把socket的发送缓冲中的数据发送完,如果len小于剩余 空间大小send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把socket的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到socket的发送缓冲区的剩余空间里)。如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。
要注意send函数把msg中的数据成功copy到socket的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。
注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
7数据接收函数 TCP使用
int recv( int socket,void *buf,int len,unsigned int flags);
功能:不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。实现接收远程主机发来的数据,并把这些数据保存在一个数组中。
返回:成功返回接收到的字符数,失败-1
参数1:socket指定接收端套接字描述符;
参数2:buf指明一个指针数组,该数组用来存放recv函数接收到的数据;
参数3:len指明buf数组的长度;
参数4:flags一般置0。
这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,recv先等待socket的发送缓冲中的数据被协议传送完毕,如果协议在传送socket的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,如果socket的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字socket的接收缓冲区,如果socket接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把socket的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以 在这种情况下要调用几次recv函数才能把socket的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
8 write与read函数
ssize_t write (int fd, const void *buf, size_t count)
ssize_t read (int fd, void *buf, size_t count)
功能:write函数用来向文件中写入数据,read函数用来从文件中读取数据。在网络编程中,当socket建立后,向这个socket种写入数据即表示向远程主机传送数据,从socket读取数据则相当于接收远程主机传过来的数据。二者的作用分别与send和recv函数类似。
返回:成功返回已写入或已读出的字节数,失败-1
参数1:表示已建立的socket
参数2:buf指向一段内存的指针
参数3:count表示buf指向内存的长度
8获得和设置当前套接字选项特定属性的值
Int getsockopt(int sockfd,int level,int optname,void *optval,socklen_t*optlen)
Int setsockopt(int sockfd,int level,int optname,const void *optval,socklen_t optlen)
返回:0成功,-1失败
参数1:sockfd套接字描述符
参数2:level套接字选项的协议层level
参数3:optname套接字选项条目名称
参数4:optval套接字选项接收缓冲区的指针
参数5:选项的输入缓冲区长度及返回的选项缓冲区长度指针optlen和*optlen
协议层参数level代表套接字选项所在的协议层次。
9 I/O多路复用
I/O多路复用应用场合:
1) 客户端同时处理多个文件描述符
2) 客户端要同时处理多个网络套接字
3) TCP服务器同时处理监听套接字和连接套接字
4) 服务器同时处理TCP和UDP
I/O多路复用时,应用程序在执行Select函数系统调用的时候被阻塞,而不是被阻塞在实际的I/O系统调用阶段。Select函数允许进程指示多个事件中的一个或多个的发生,或者若在规定的时间内没有任何事件发生,内核唤醒应用进程进行后续处理。
展开阅读全文