首先介绍两个数据结构及相关的操作函数:struct iovec、struct msghdr

struct iovec {

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

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

};

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

ssize_t readv(int s, const struct iovec *vector, int count);

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

ssize_t writev(int fd, const iovec *vector, int count);

返回值为成功发送的字节数。   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>
#define Serv_Port 8888
#define BackLog 5
void process_client_vector(int sock_cli); int main(char *argv[], int argc)
{
int sock_serv, sock_cli;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr; int err;
pid_t handle_client_pid; sock_serv = socket(AF_INET, SOCK_STREAM, );
if(sock_serv < ){
printf("Error When build Socket\n");
return ;
} 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, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(err < ){
printf("Error When Bind\n");
return ;
} err = listen(sock_serv, BackLog);
if(err < ){
printf("Error When Listen\n");
return ;
} // while(1){
int addrlen = sizeof(struct sockaddr);
printf("Waiteing... ...\n");
sock_cli = accept(sock_serv, (struct sockaddr*)&client_addr, &addrlen); if(sock_cli < )
;//continue;
handle_client_pid = fork();
if(handle_client_pid == ){
close(sock_serv);
process_client_vector(sock_cli);
}
else
close(sock_cli);
// }
} void process_client_vector(int sock_cli)
{
int number;
char str;
char ch;
int i = ;
printf("One client is Accpted\n");
struct iovec *recv_vector = (struct iovec*)malloc(*sizeof(struct iovec)); if(!recv_vector){
printf("NO Enough Space Here\n");
return;
} recv_vector[].iov_base = &number;
recv_vector[].iov_len = sizeof(number); recv_vector[].iov_base = &str;
recv_vector[].iov_len = sizeof(str); recv_vector[].iov_base = &ch;
recv_vector[].iov_len = sizeof(ch); ssize_t size = readv(sock_cli, recv_vector, );
printf("RECVED: Number%d STR: %c CHAR:%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> #define Serv_Port 8888
void process_server_vector(int sock_cli); int main(char *argv[], int argc)
{
struct sockaddr_in server_addr;
int err;
int sock_cli; sock_cli = socket(AF_INET, SOCK_STREAM, );
if(sock_cli < ){
printf("Error When Socket()\n");
return ;
} 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, (struct sockaddr *)&server_addr, sizeof(server_addr)); process_server_vector(sock_cli); close(sock_cli); return ;
} void process_server_vector(int sock_cli)
{
int number = ;
char str = 'K';
char ch = 'M';
ssize_t size = ; struct iovec *vector = (struct iovec *)malloc(*sizeof(struct iovec)); vector[].iov_base = &number;
vector[].iov_len = sizeof(number); vector[].iov_base = &str;
vector[].iov_len = sizeof(str); vector[].iov_base = &ch;
vector[].iov_len = sizeof(ch); size = writev(sock_cli, vector, );
if(size < )
printf("Writev Error\n");
}

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

 struct msghdr {
void *msg_name; /* ptr to socket address structure */
int msg_namelen; /* size of socket address structure */
struct iovec *msg_iov; /* scatter/gather array */
__kernel_size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data */
__kernel_size_t msg_controllen; /* ancillary data buffer length */
unsigned int msg_flags; /* flags on received message */
}; 这个数据结构如果不考虑msg_falsgs,与struct iovec的用法并没有很大的差别,操作这个数据结构的函数:
#include<sys/uio.h>
ssize_t recvmsg(int s, const struct msghdr *msg, int flags);
s: 套接字 msg:承接数据的消息数据结构 flags:没有很大的意义,
ssize_t sendmsg(int s, const struct msghdr *msg, int flags );
s: 套接字             msg:承接数据的消息数据结构   flags:决定以什么方式发送数据
readmsg的接收方式取决于msg结构中msg_flags的值,这也是readmsg()与函数sendmsg()的不同的地方,sendmsg()函数的发送方式有参数决定。

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

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


int read(int fd, void * buffer, int nbyte);
int write(int handle, void *buf, int nbyte);
这两个函数可以用于任何的描述符,可以用于文件,标准输入输出,和套接字。 readv(), writev(),recvmsg(),sendmsg()的具体函数参考上面的具体内容。 int recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen);
s: 套接字  buf:数据接收缓冲区  len:接收数据长度 flags:是以下一个或者多个标志的组合体,可通过or操作连在一起
from:数据的来源的地址 fromlen: 地址长度。
 

Linux 网络编程基础(3) -- 数据的IO的更多相关文章

  1. 服务器编程入门(4)Linux网络编程基础API

      问题聚焦:     这节介绍的不仅是网络编程的几个API     更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系.     这节主要介绍三个方面的内容:套接字( ...

  2. Linux 高性能服务器编程——Linux网络编程基础API

    问题聚焦:     这节介绍的不仅是网络编程的几个API     更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系.     这节主要介绍三个方面的内容:套接字(so ...

  3. 第5章 Linux网络编程基础

    第5章 Linux网络编程基础 5.1 socket地址与API 一.理解字节序 主机字节序一般为小端字节序.网络字节序一般为大端字节序.当格式化的数据在两台使用了不同字节序的主机之间直接传递时,接收 ...

  4. Linux网络编程基础API

    第5章 Linux网络编程基础API 探讨Linux网络编程基础API与内核中TCP/IP协议族之间的关系,并未后续章节提供编程基础.从3个方面讨论Linux网络API. socket地址API.so ...

  5. linux高性能服务器编程 (五) --Linux网络编程基础api

    第五章 Linux网络编程基础api 1.主机字节序和网络字节序 字节序是指整数在内存中保存的顺序.字节序分为大端字节序.小端字节序. 大端字节序:一个整数的高位字节数据存放在内存的低地址处.低位字节 ...

  6. linux 网络编程 基础

    网络编程基础 套接字编程需要指定套接字地址作为参数,不同的协议族有不同的地址结构,比如以太网其结构为sockaddr_in. 通用套接字: struct sockaddr { sa_family_t ...

  7. linux网络编程基础--(转自网络)

    转自 http://www.cnblogs.com/MyLove-Summer/p/5215287.html Linux下的网络编程指的是socket套接字编程,入门比较简单. 1. socket套接 ...

  8. Linux网络编程基础

    1. Linux网络模型 ① OSI七层模型和Linux四层模型 ② 各种协议之间的关系及在Linux模型中的位置 ③ 协议封装:各种协议处于一种层层封装的关系 (1)Ethernet (2)IP * ...

  9. 5 Linux网络编程基础API

    5.1   socket地址API 大端字节序(网络序):高位在低址,低位在高址 小端字节序(主机序):低位在低址,高位在高址 判断,利用联合的特性: #include <iostream> ...

随机推荐

  1. mysql-5.7.10-winx64 MySQL服务无法启动,服务没有报告任何错误的解决办法

      总结报错原因:在my.init文件下新增data目录(datadir = F:\mysqldata ) 最新解压版本的mysql 解压安装的时候报错D:\mysql\mysql-5.7.10-wi ...

  2. 教你如何利用初级C#语言更改银行存款!!!!

    您是否对生活现状不满意? 您是否总是感叹工资太少? 您是否经常发现自己相中的物品又降价了然而自己却还是只能望洋兴叹? 没关系!让我来拯救你的钱包! 接下来进入正题: 要想更改自己的银行存款首先得找到一 ...

  3. 【codevs】2292图灵机游戏

    题 Shadow最近知道了图灵机是什么(Shadow:就是一行格子和一个机器头移来移去的呗!),于是他突发奇想,创造了一个新游戏——“图灵机游戏”(Shadow:好听吧?). 游戏规则如下: 在一条长 ...

  4. C++虚函数在内存中的实现

    首先来一张图,一目了然: 然后把相应的代码贴上来: class A { int a; public: virtual void f(); virtual void g(int); virtual vo ...

  5. (转载)JS中的prototype

    原文地址:http://www.cnblogs.com/yjf512/archive/2011/06/03/2071914.html#!comments JS中的phototype是JS中比较难理解的 ...

  6. 图片延时加载jquery.inview.js用法详解

    我们在网站上总能见到这样的效果,若是有图片,图片都是先用loading加载一小段时间,然后紧接着出来要显示的图片,即效果如下: v2_loading.gif,几秒钟时间过渡到v2_pic_01_s.j ...

  7. 用JavaScript获取地址栏参数的方法

    /** * 获取地址栏参数 * * @example GetUrlString('id') * * @desc 调用时加上判断,保证程序不会出错 * var myurl = GetUrlString( ...

  8. MVC自学第四课

    处理表单 前面的列子我们已经把表单提交给了HomeControllers类中的RsvpForm动作方法,只是在这个动作方法内,我们并没有做什么具体的逻辑处理,而是直接返回一个 “Thanks”的视图. ...

  9. Kotlin Vertx

    Kotlin & Vertx Kotlin 是一门好语言,值得大家了解一下. Vertx 是一个好框架,也值得大家了解一下. Kotlin 写过js,也写过一点点go,主力一直是java.用了 ...

  10. JS中String添加trim()方法

    这么牛的JS竟然还要自己封装trim方法. 下面利用prototype和正则表达式的添加方式添加trim(): <script language="javascript"&g ...