该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
客户端和服务端建立了连接就可以在客户端和服务端之间传输数据了,需要两个系统调用。
--send 发送数据。
--recv 接收数据。
一个套接口既可以发送数据,也可以接收数据,网络是一个双向管道。
send()函数
ssize_t send(int s,const void *buf,size_t len,int flags);
send函数用来发送数据。
参数s是已经建立连接的套接口。
参数buf是发送数据内存buffer地址指针。
参数len指明buffer的大小,单位字节。
参数flags一般填0.
成功返回发送的字节数,失败返回-1,并设置errno。
send()函数注意点
1.send返回值理解
send在阻塞场景下,返回值要么是指定长度(发送成功),要么是-1,发送失败,但是在非阻塞场景下,
返回值可能小于指定长度,这是因为发送数据超过发送缓冲区(窗口),所以只能发送缓冲区大小的数据,剩下的数据无法发送
2.errno=11的理解
send在非阻塞场景可能返回-1,并且更新errno为11,11表示资源临时不可用,当发送缓冲区满了,
而程序不断在调用send(0函数发送数据就会出现这个错误,此时收到返回值为-1,并且errno=11时,需要停止发送数据,等待套接字下次可写的时候再发送数据。
recv()函数
ssize_t recv(int s,void *buf,size_t len,int flags);
recv函数用来接收数据。
参数s是已经建立连接的套接口。
参数buf是接收数据内存buffer地址指针。
参数len指明buffer的大小,单位字节。
参数flags一般填0.
成功返回接收到的字节数,失败返回-1,并且设置errno,如果对端套接字已经关闭,返回0.
recv函数只是从TCP缓存中读数据(此时数据已经在自己的电脑上了),不是直接从网络中读数据,什么时候TCP缓存区满了,另一边的send函数才会停止发送数据。
recv()函数会阻塞线程,直到收到消息或者客户端关闭。
最后当你用完套接口以后,就该释放套接口所占用的资源了,通过close做到这一点
当试图向一个已经关闭的套接口写或者读数据就会出错。
setsockopt()函数
int setsockopt(int s,int level,int optname,const void *optval,socklen optlen);
setsockopt函数设置套接口
函数成功返回0,失败返回-1,并设置errno
常见用法为:
int on=1;
setsockopt(st,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
由于TCP套接字状态TIME_WAIT引起该套接字关闭后约保留2到4分钟。在此期间bind绑定该端口失败。
SO_REUSEADDR指示系统地址可重用。
当服务器在listen()函数后直接退出,如果这时候有一个客户端来连接,这个连接会被放在缓存中,如果这时候启动了一个新的程序绑定这个IP地址和端口号,
那么这新的程序就会接收到上一个客户端的请求,这是有问题,因为上一个客户端请求访问的是原始程序。但是如果我们就一直一个程序绑定这个IP地址,就用不着这个TIME_WAIT信号了,
我们服务器上就一个server绑定这个IP地址和端口号,所以用不着这个机制,因此调用setsockopt()函数。
IP地址的结构
ip地址在内存中用int表示,int在内存中占有4个字节的空间
第一个字节:192
第二个字节:168
第三个字节:1
第四个字节:2