您的位置:首页 > 理论基础 > 计算机网络

Linux 网络编程基础(3) -- 数据的IO

2014-04-09 20:24 387 查看
首先介绍两个数据结构及相关的操作函数:structiovec、structmsghdr

structiovec{

  void*iov_base;/*向量的缓冲地址*/

  size_tiov_len;  /*向量缓冲区的大小,以字节为单位*/

};

iovec定义在linux/include/uio.h中,此数据结构与readv()和writev()联合使用。

ssize_treadv(ints,conststructiovec*vector,intcount);

返回值为成功接收的字节数。s:文件描述符vector:iovec数组的起始地址count:iovec数组的元素个数。

ssize_twritev(intfd,constiovec*vector,intcount);

返回值为成功发送的字节数。fd:文件描述符vector:发送数据的vector数组地址count:iovec数组的元素个数

应用的例子:

/*
服务器端代码
*/

#include<stdio.h>
#include<stdlib.h>
#include<strings.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<sys/uio.h>
#include<netinet/in.h>
#defineServ_Port8888
#defineBackLog5
voidprocess_client_vector(intsock_cli);

intmain(char*argv[],intargc)
{
intsock_serv,sock_cli;
structsockaddr_inserver_addr;
structsockaddr_inclient_addr;

interr;
pid_thandle_client_pid;

sock_serv=socket(AF_INET,SOCK_STREAM,0);
if(sock_serv<0){
printf("ErrorWhenbuildSocket\n");
return1;
}

bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(Serv_Port);
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);

err=bind(sock_serv,(structsockaddr*)&server_addr,sizeof(server_addr));
if(err<0){
printf("ErrorWhenBind\n");
return1;
}

err=listen(sock_serv,BackLog);
if(err<0){
printf("ErrorWhenListen\n");
return1;
}

//while(1){
intaddrlen=sizeof(structsockaddr);
printf("Waiteing......\n");
sock_cli=accept(sock_serv,(structsockaddr*)&client_addr,&addrlen);

if(sock_cli<0)
;//continue;
handle_client_pid=fork();
if(handle_client_pid==0){
close(sock_serv);
process_client_vector(sock_cli);
}
else
close(sock_cli);
//}
}

voidprocess_client_vector(intsock_cli)
{
intnumber;
charstr;
charch;
inti=0;
printf("OneclientisAccpted\n");
structiovec*recv_vector=(structiovec*)malloc(3*sizeof(structiovec));

if(!recv_vector){
printf("NOEnoughSpaceHere\n");
return;
}

recv_vector[0].iov_base=&number;
recv_vector[0].iov_len=sizeof(number);

recv_vector[1].iov_base=&str;
recv_vector[1].iov_len=sizeof(str);

recv_vector[2].iov_base=&ch;
recv_vector[2].iov_len=sizeof(ch);

ssize_tsize=readv(sock_cli,recv_vector,3);
printf("RECVED:Number%dSTR:%cCHAR:%c\n",number,str,ch);

}


/*
客户器端代码
*/

#include<stdio.h>
#include<stdlib.h>
#include<strings.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<sys/uio.h>
#include<netinet/in.h>

#defineServ_Port8888
voidprocess_server_vector(intsock_cli);

intmain(char*argv[],intargc)
{
structsockaddr_inserver_addr;
interr;
intsock_cli;

sock_cli=socket(AF_INET,SOCK_STREAM,0);
if(sock_cli<0){
printf("ErrorWhenSocket()\n");
return1;
}

bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(Serv_Port);
inet_pton(AF_INET,"127.0.0.1",&server_addr.sin_addr);

connect(sock_cli,(structsockaddr*)&server_addr,sizeof(server_addr));

process_server_vector(sock_cli);

close(sock_cli);

return0;
}

voidprocess_server_vector(intsock_cli)
{
intnumber=10;
charstr='K';
charch='M';
ssize_tsize=0;

structiovec*vector=(structiovec*)malloc(3*sizeof(structiovec));

vector[0].iov_base=&number;
vector[0].iov_len=sizeof(number);

vector[1].iov_base=&str;
vector[1].iov_len=sizeof(str);

vector[2].iov_base=&ch;
vector[2].iov_len=sizeof(ch);

size=writev(sock_cli,vector,3);
if(size<0)
printf("WritevError\n");
}


msghdr结构体定义在linux/include/socket.h中

structmsghdr{
void*msg_name;/*ptrtosocketaddressstructure*/
intmsg_namelen;/*sizeofsocketaddressstructure*/
structiovec*msg_iov;/*scatter/gatherarray*/
__kernel_size_tmsg_iovlen;/*#elementsinmsg_iov*/
void*msg_control;/*ancillarydata*/
__kernel_size_tmsg_controllen;/*ancillarydatabufferlength*/
unsignedintmsg_flags;/*flagsonreceivedmessage*/
};

这个数据结构如果不考虑msg_falsgs,与structiovec的用法并没有很大的差别,操作这个数据结构的函数:
#include<sys/uio.h>
ssize_trecvmsg(ints,conststructmsghdr*msg,intflags);
s:套接字msg:承接数据的消息数据结构flags:没有很大的意义,
ssize_tsendmsg(ints,conststructmsghdr*msg,intflags);

s:套接字msg:承接数据的消息数据结构flags:决定以什么方式发送数据

readmsg的接收方式取决于msg结构中msg_flags的值,这也是readmsg()与函数sendmsg()的不同的地方,sendmsg()函数的发送方式有参数决定。

在没有介绍套接字的选项前,先不对msghdr的相关代码编写进行实践,因为msghdr中的msg_name,msg_control,msg_flags等成员的设定与当前使用的协议是相关的,待以后把套接字的选项介绍完后,在深入探究msghdr的使用。

除了上述介绍的几个函数,还有很多的IO函数,现总结如下:


intread(intfd,void*buffer,intnbyte);
intwrite(inthandle,void*buf,intnbyte);
这两个函数可以用于任何的描述符,可以用于文件,标准输入输出,和套接字。

readv(),writev(),recvmsg(),sendmsg()的具体函数参考上面的具体内容。

intrecvfrom(ints,void*buf,intlen,unsignedintflags,structsockaddr*from,int*fromlen);
s:套接字  buf:数据接收缓冲区  len:接收数据长度flags:是以下一个或者多个标志的组合体,可通过or操作连在一起
from:数据的来源的地址fromlen:地址长度。


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: