首先介绍两个数据结构及相关的操作函数: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. C语言栈的实现

    栈是常用的数据结构之一,下面给出一个链式栈的实现~~头文件Stack.h #ifndef Stack_H #define Stack_H typedef int Item; typedef struc ...

  2. EBS OAF中如何在多行表中实现附件功能

    EBS OAF中如何在多行表中实现附件功能 (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 在OAF中使用附件功能之前,要先明白Entity( ...

  3. 区分IE9/IE8/IE7/IE6及其他浏览器-CSS hack

    记录一下这些浏览器的hack如下: 一.IE9以及以下版本浏览器 对于IE8及其以下版本的浏览器,就是使用本文标题所提到的”\9″ hack.如下代码: .ie8_9{ color:blue; /*所 ...

  4. Android API在不同版本系统上的兼容性

    随着安卓版本的不断更新,新的API不断涌出,有时候高版本的API会在低版本crash的. 如果minSdkVersion设置过低,在build的时候,就会报错(Call requires API le ...

  5. < meta > 元素 概要

    < meta > 元素 概要 标签提供关于HTML文档的元数据.元数据不会显示在页面上,但是对于机器是可读的.它可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 we ...

  6. codeforces 3D . Least Cost Bracket Sequence 贪心

    题目链接 给一个字符串, 由( ) 以及? 组成, 将?换成( 或者 ) 组成合法的括号序列, 每一个?换成( 或者 ) 的代价都不相同, 问你最小代价是多少, 如果不能满足输出-1. 弄一个变量nu ...

  7. echarts实现上海地域PM值(map、timeline)

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  8. 关于scp 不需要密码

    运行 ssh-keygen -t rsa 会在用户目录~/.ssh/产生两个文件,id_rsa,id_rsa.pub   //      cat id_rsa.pub >~/.ssh/autho ...

  9. 《转》Java 信号量 Semaphore 介绍

    该文章转自:http://www.cnblogs.com/whgw/archive/2011/09/29/2195555.html Semaphore当前在多线程环境下被扩放使用,操作系统的信号量是个 ...

  10. wpf中的触发器详解

    原文 http://zwkufo.blog.163.com/blog/static/25882512009724113250883/ 7.1.2 简单逻辑的表示--触发器(1) 在本章的多处介绍中都会 ...