首先介绍两个数据结构及相关的操作函数: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. SQLSERVER分布式事务使用实例

    实例一 尊重原著作:本文参考自http://www.jb51.net/article/43540.htm --BEGIN DISTRIBUTED TRANSACTION [transactionnam ...

  2. hibernate 简单查询

    1. 查询整个映射对象所有字段 //直接from查询出来的是一个映射对象,即:查询整个映射对象所有字段           String hql = "from Users";   ...

  3. php simple_html_dom 一个iconv错误引起解析中断的问题,貌似内存溢出

    环境: $pageNum = 8; for ($i = 1; $i < $pageNum; $i++) { $html = new simple_html_dom(); $host = 'htt ...

  4. getchar()用法

    getchar() .从缓冲区读走一个字符,相当于清除缓冲区 .前面的scanf()在读取输入时会在缓冲区中留下一个字符'\n'(输入完s[i]的值后按回车键所致),所以如果不在此加一个getchar ...

  5. Arduino周边模块:LED部件

    Arduino周边模块:LED部件 Arduino周边模块:LED部件 1. LED的使用 LED的原理: LED是会发光的二极管,它具有单向导电性.两端加上正向电压,即能将电能转化为光能. 正向电压 ...

  6. [LeetCode]题解(python):149-Max Points on a Line

    题目来源: https://leetcode.com/problems/max-points-on-a-line/ 题意分析: 在一个2D的板上面有很多个点,判断最多有多少个点在同一条直线上. 题目思 ...

  7. 括号匹配算法 C语言实现

    #include <stdio.h> #include <malloc.h> //malloc,realloc #include <math.h> //含有over ...

  8. SQL Server 固定角色

    1. 查看固定服务器角色 execute sp_helpsrvrole; 管理: execute master..sp_addsrvrolemember @logingName='neeky' @ro ...

  9. C语言入门(4)——常量、变量与赋值

    对于基本数据类型量,按其取值是否可改变又分为常量和变量两种.在程序执行过程中,其值不发生改变的量称为常量,其值可变的量称为变量.它们可与数据类型结合起来分类. 常量 常量有字符常量(Character ...

  10. CentOS 删除自带的OpenJDK 和 安装SunJDK

    [root@WX32 local]# java -version java version "1.6.0" OpenJDK Runtime Environment (build - ...