关于linux的读写操作
建立了连接,就可以进行通讯了,往文件描述符里读写,和读写文件是一样的.
写函数:
ssize_t write(int fd,(void *)buf,size_t nbytes)
将buf中的nbytes写入到fd中,成功时返回所写的字节数,失败时返回-1,并写入errno变量.
当我们象套接字写数据时,可能会有两种情况:
a.write的返回值大于0,表示写了部分或者是全部的数据
b.返回的值小于0,此时出现了错误.我们要根据错误类型来处理
如果错误为EINTR表示在写的时候出现了中断错误.
如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接).
读函数:
ssize_t read(int fd,(void *)buf,size_t nbytes)
从fd中读内容,当读成功时,返回读入的字节数,返回是0,责表示已经读入到文件结束了,小于0表示出现了错误.
数据报的发送:
int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);
int sendto(int sockfd,const void *msg,int len,unsigned int flags,struct sockaddr *to,int tolen);
sockfd,buf,len的意义和read,write一样,分别表示套接字描述符,发送或接收的缓冲区及大小.recvfrom负责从sockfd接收数据,如果from不NULL,那么在from里面存储了信息来源的情况,如果对信息的来源不感兴趣,可以将from和fromlen设置为NULL.sendto负责向to发送信息.此时在to里面存储了收信息方的详细资料.
高级套接字函数:
int recv(int sockfd,void *buf,int len,int flags)
int send(int sockfd,void *buf,int len,int flags)
前面的三个参数和read()和write()函数一样的,参数flags可以是0或者以下任何一项:
MSG_DONTROUTE:是send()函数使用的标识,告诉IP协议,目的主机在本网络上面,没有必要查找路由表;
MSG_OOB:接受或者发送附带数据;
MSG_PEEK:recv()函数使用的参数,表示只从系统缓冲区中读取数据,而不清除系统缓冲的内容,一般在多个进程读写数据的时候使用;
MSG_WAITALL:是recv()函数使用的参数,表示等到所有的数据到达后才返回.使用这个参数时,recv()函数会一直阻塞.
套接字的关闭:
套接字的关闭有两个函数:
shutdown()和close()
int shutdown(int sockfd,int howto)
TCP连接是双向的(是可读写的),当我们使用close时,会把读写通道都关闭,有时侯我们希望只关闭一个方向,这个时候我们可以使用shutdown.针对不同的howto,系统回采取不同的关闭方式.
howto=0这个时候系统会关闭读通道.但是可以继续往接字描述符写.
howto=1关闭写通道,和上面相反,着时候就只可以读了.
howto=2关闭读写通道,和close一样 在多进程程序里面,如果有几个子进程共享一个套接字时,如果我们使用shutdown, 那么所有的子进程都不能够操作了,这个时候我们只能够使用close来关闭子进程的套接字描述符.
ioctl函数:
ioctl()函数可以控制所有的文件描述符的情况,这里介绍一下控制套接字的选项:
int ioctl(int fd,int req...)
ioctl的控制选项:
SIOCATMARK:是否到达外带标记;
FIOASYNC:异步输入/输出标识;
FIONREAD:缓冲区的可读字节数.
循环服务器:UDP服务器
UDP循环服务器的实现很简单:UDP服务器每次从套接字上读取一个客户端的请求,处理, 然后将结果返回给客户机.
socket(...);
bind(...);
while(1)
{
recvfrom(...);
process(...);
sendto(...);
}
因为UDP是非面向连接的,没有一个客户端可以老是占住服务端. 只要处理过程不是死循环, 服务器对于每一个客户机的请求总是能够满足.
循环服务器:TCP服务器
TCP循环服务器的实现也不难:TCP服务器接受一个客户端的连接,然后处理,完成了这个客户的所有请求后,断开连接.
socket(...);
bind(...);
listen(...);
while(1)
{
accept(...);
while(1)
{
read(...);
process(...);
write(...);
}
close(...);
}
TCP循环服务器一次只能处理一个客户端的请求.只有在这个客户的所有请求都满足后, 服务器才可以继续后面的请求.这样如果有一个客户端占住服务器不放时,其它的客户机都不能工作了.因此,TCP服务器一般很少用循环服务器模型的.
并发服务器:TCP服务器
为了弥补循环TCP服务器的缺陷,人们又想出了并发服务器的模型. 并发服务器的思想是每一个客户机的请求并不由服务器直接处理,而是服务器创建一个 子进程来处理.
socket(...);
bind(...);
listen(...);
while(1)
{
accept(...);
if(fork(..)==0)
{
while(1)
{
read(...);
process(...);
write(...);
}
close(...);
exit(...);
}
close(...);
}
TCP并发服务器可以解决TCP循环服务器客户机独占服务器的情况. 不过也同时带来了一个不小的问题.为了响应客户机的请求,服务器要创建子进程来处理. 而创建子进程是一种非常消耗资源的操作.
声明:网上资料收集,并非本人所写.