(51)LINUX应用编程和网络编程之六Linux高级IO

3.6.1.非阻塞IO

3.6.1.1、阻塞与非阻塞

阻塞:阻塞具有很多优势(是linux系统的默认设置),单路IO的时候使用阻塞式IO没有降低CPU的性能

补充:阻塞/非阻塞, 它们是程序在等待消息(无所谓同步或者异步)时的状态.

阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。

有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。

对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。

非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

3.6.1.2、为什么有阻塞式

(1)常见的阻塞:wait(显式回收子进程)、pause、sleep等默认阻塞函数;read或write某些文件时也是默认阻塞式的

(2)阻塞式的好处:当前线程被挂起等待条件满足才返回结果

3.6.1.3、非阻塞

(1)为什么要实现非阻塞

(2)如何实现【非阻塞IO访问】:

1)打开文件时加入O_NONBLOCK

2)fcntl函数,对文件描述符(文件已经打开)进行操作

单路IO就用阻塞式比较好;

多路IO最好是用非阻塞式的。避免资源被一个占有不放,让其他IO有资源可抢。

从CPU的利用角度来看,单路IO就是一对一;多路IO就是一对多,即一个CPU对应多个资源抢占通道。前者单路效率更高,后者需要兼顾分配。单路IO模型只需要监听一个IO流,多路IO模型可以同时监听(内部轮循)多个IO流,CPU要不停去查看。

3.6.2.阻塞式IO的困境

3.6.2.1、程序中读取键盘

3.6.2.2、程序中读取鼠标        cat         /dev/input/mouse1

3.6.2.3、程序中同时读取键盘和鼠标

3.6.2.4、问题分析

并不是所有的情况下都适阻塞式io的。

代码示例:

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/stat.h>

/*

程序中读取键盘和鼠标

*/

#define NAME     "/dev/input/mouse1"

char buff[100]={0};

char buf[100]={0};

int main(int argc,char **argv)

{

int ssize_t=-1;

int fd=-1;

fd=open(NAME,O_RDWR);

if(-1==fd)

{

perror("open");

_exit(-1);

}

printf("打开成功!fd=%d\n",fd);

while(1){

ssize_t=read(fd,buff,sizeof(buff));

if(-1==ssize_t)

{

perror("read");

_exit(-1);

}

printf("读到的鼠标字符数为%d\n",ssize_t);

printf("读到的鼠标字符是[%s]\n",buff);

read(0,&buf,sizeof(buf));

printf("读到的鼠标字符是[%s]\n",buf);

sleep(1);

}

return 0;

}

3.6.3.并发式IO的3种解决方案【并发式IO】

3.6.3.1、非阻塞式IO:性能不够好,有点类似于轮询的方式,CPU不停的去查看

代码示例:

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#define NAME     "/dev/input/mouse1"

char buff[100]={0}; //键盘

char buf[100]={0};//鼠标

int main(void)

{

int ssize_t=-1;

int fd=-1;

int flag=-1;

int ret=-1;

fd=open(NAME,O_RDWR | O_NONBLOCK );

if(-1==fd)

{

perror("open");

_exit(-1);

}

//把标准输入文件描述符0通过fcntl函数变成非阻塞式子

// 把0号文件描述符(stdin)变成非阻塞式的

flag = fcntl(0, F_GETFL);        // 先获取原来的flag

flag |= O_NONBLOCK;                // 添加非阻塞属性

fcntl(0, F_SETFL, flag);        // 更新flag

// 这3步之后,0就变成了非阻塞式的了

while (1)

{

// 读鼠标

memset(buf, 0, sizeof(buf));

//printf("before 鼠标 read.\n");

ret = read(fd, buf, 50);

if (ret > 0)

{

printf("鼠标读出的内容是:[%s].\n", buf);

}

// 读键盘

memset(buff, 0, sizeof(buff));

//printf("before 键盘 read.\n");

ret = read(0, buff, 5);

if (ret > 0)

{

printf("键盘读出的内容是:[%s].\n", buff);

}

}

return 0;

}

3.6.3.2、多路复用IO :性能相对比较好,解决并发性IO的解决

3.6.4.IO多路复用原理

3.6.4.1、何为IO多路复用   【说白了,多路复用其实就是一个管多个】

(1)IO           multiplexing

(2)用在什么地方?多路非阻塞式IO(多路及时响应)。

(3)select和poll两个函数:(poll出现的比较晚一点。其性能也要比select函数的性能更好一些)

(4)外部阻塞式(select和poll两个函数本身在调用的时候是阻塞式的,对外表现为阻塞式),内部非阻塞式(

两个函数内部实现的时候,也就是当把要监听的东西(比如A和B两个阻塞式IO)放在这个函数的监听范围)【自动】轮询【这两个多路阻塞式IO】               (轮询的意思就是CPU不停的去查看)

补充:

可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要

等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。

3.6.4.2、select函数介绍:

#include <sys/select.h>

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

int select(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds, struct timeval *timeout);     //nfds表示文件描述符的个数 nfds is the highest-numbered file descriptor in any of the //three sets, plus 1,是指集合中所有文件描述符的范围,【即所有文件描述符的最大值加1】这一点要注意,所有文件描述符的最大值加1,比如一个文件描述符是0,一个文件描述符是1,则为1+1

相关函数:

(1)void FD_ZERO(fd_set *set);       //把文件描述符集合清零

(2)void FD_SET(int fd, fd_set *set);   //把某个文件描述符添加到这个集合中去

(3)int  FD_ISSET(int fd, fd_set *set);

//检查集合中指定的文件描述符是否可以读写 FD_ISSET() tests to see if a file descriptor is part of the set; this is useful after select() returns.

(4)void FD_CLR(int fd, fd_set *set);   //把一个给定的文件描述符从集合中删除

相关结构体:

(1)struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(file descriptor)。

(2)

struct timeval {

long    tv_sec;         /* seconds */

long    tv_usec;        /* microseconds */

};

struct timeval* timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。

linux内部代码示例:

#include <stdio.h>

#include <stdlib.h>

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

int main(void)

{

fd_set rfds;

struct timeval tv;

int retval;

/* Watch stdin (fd 0) to see when it has input. */

FD_ZERO(&rfds);   //先把文件描述符集合清零

FD_SET(0, &rfds);   //把0文件描述符添加到这个集合中去

/* Wait up to five seconds. */

tv.tv_sec = 5;

tv.tv_usec = 0;

retval = select(1, &rfds, NULL, NULL, &tv);

/* Don‘t rely on the value of tv now! */

if (retval == -1)

perror("select()");

else if (retval)

printf("Data is available now.\n");

/* FD_ISSET(0, &rfds) will be true. */

else

printf("No data within five seconds.\n");

exit(EXIT_SUCCESS);

}

3.6.4.3、poll函数介绍

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

#define _GNU_SOURCE         /* See feature_test_macros(7) */

结构体:

struct pollfd {

int   fd;         /* file descriptor */

short events;     /* requested events */

short revents;    /* returned events */

};

代码示例:

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <poll.h>

/*

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

*/

#define NAME  "/dev/input/mouse1"

int main(void)

{

char buf[100]={0};                 //注意这里的定义的buf不能够使用全局的

//int poll(struct pollfd *fds, nfds_t nfds, int timeout);

struct pollfd a[2]={0};

int fd= open(NAME,O_RDWR);   //定义鼠标文件描述符

if(fd<0)

{

perror("open mouse");

_exit(-1);

}

//实例化结构体

a[0].fd=fd;               //鼠标

a[0].events=POLLIN;

a[1].fd=0;                 //键盘

a[1].events=POLLIN;

int ret=poll(a,fd+1,10000);

if(ret<0)

{

perror("poll");

_exit(-1);

}

if(ret==0)

{

printf("超时了");

}

else     //判断是谁发生了IO

{

if(a[0].events==a[0].revents)        //鼠标

{

memset(buf,0,sizeof(buf));

read(fd,buf,10);

printf("读出来的鼠标内容是:[%s]\n",buf);

}

if(a[1].events==a[1].revents)        //键盘

{

memset(buf,0,sizeof(buf));

read(0,buf,50);

printf("读出来的键盘内容是:[%s]\n",buf);

}

}

return 0;

}

3.6.5.IO多路复用实践

3.6.5.1、用select函数实现同时读取键盘鼠标

select()函数实现IO多路复用的步骤

(1)清空描述符集合

(2)建立需要监视的描述符与描述符集合的关系

(3)调用select函数

(4)检查监视的描述符判断是否已经准备好

(5)对已经准备好的描述符进程IO操作

代码示例:

/*

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

*/

#include <stdio.h>

#include <stdlib.h>

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

#define NAME     "/dev/input/mouse1"

char buf[100]={0};

int main(void)

{

int fd=-1;

fd_set readfds=-1;

struct timeval time;

int ret=-1;

fd=open(NAME,O_RDWR);

printf("fd=%d\n",fd);

if(-1==fd)

{

perror("open");

_exit(-1);

}

FD_ZERO(&readfds);    //清除文件描述符集合

FD_SET(fd,&readfds);

FD_SET(0,&readfds);

time.tv_sec=5;            //设置时间为5秒

time.tv_usec=0;

ret=select(3,&readfds,NULL,NULL,&time);           //调用select函数 ,注意第一个参数

if (ret < 0)                      //表示出错

{

perror("select: ");

return -1;

}

else if (ret == 0)              //表示超过了规定的时间限制

{

printf("超时了\n");

}

else

{

// 等到了一路IO,然后去监测到底是哪个IO到了,处理之

if (FD_ISSET(0, &readfds))

{

// 这里处理键盘

memset(buf, 0, sizeof(buf));

read(0, buf, 5);

printf("键盘读出的内容是:[%s].\n", buf);

}

if (FD_ISSET(fd, &readfds))

{

// 这里处理鼠标

memset(buf, 0, sizeof(buf));

read(fd, buf, 50);

printf("鼠标读出的内容是:[%s].\n", buf);

}

}

return 0;

}

3.6.5.2、用poll函数实现同时读取键盘鼠标

poll函数介绍:

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

第一个参数 pollfd 结构体定义如下:

引用

/* Data structure describing a polling request.  */

struct pollfd

{

int fd;                         /* poll 的文件描述符.  */

short int events;           /* fd 上感兴趣的事件(等待的事件或者说是监视的事件).  */

short int revents;          /* fd 上实际发生的事件.  */

};

fd 成员表示感兴趣的,且打开了的文件描述符;

events  成员是位掩码,用于指定针对这个文件描述符感兴趣的事件;

revents  成员是位掩码,用于指定当 poll 返回时,在该文件描述符上已经发生了哪些事情。

events 和 revents 结合下列常数值(宏)指定即将唤醒的事件或调查已结束的 poll() 函数被唤醒的原因,这些宏常数如下:

POLLIN

events 中使用该宏常数,能够在折本文件的可读情况下,结束 poll() 函数。相反,revents 上使用该宏常数,在检查 poll() 函数结束后,可依此判断设备文件是否处于可读状态(即使消息长度是 0)。

POLLPRI

在 events 域中使用该宏常数,能够在设备文件的高优先级数据读取状态下,结束 poll() 函数。相反,revents 上使用该宏常数,在检查 poll() 函数结束后,可依此判断设备文件是否处于可读高优先级数据的状态(即使消息长度是 0)。该宏常数用于处理网络信息包(packet) 的数据传递。

POLLOUT

在 events 域中使用该宏常数,能够在设备文件的写入状态下,结束 poll() 函数。相反,revents 域上使用该宏常数,在检查 poll() 结束后,可依此判断设备文件是否处于可写状态。

POLLERR

在 events 域中使用该宏常数,能够在设备文件上发生错误时,结束 poll() 函数。相反,revents 域上使用该宏函数,在检查 poll() 函数结束后,可依此判断设备文件是否出错。

POLLHUP

在 events 域中使用该宏常数,能够在设备文件中发生 hungup 时,结束 poll() 函数 。相反,在检查 poll() 结束后,可依此判断设备文件是否发生 hungup 。

POLLNVAL

在 events 域中使用该宏函数,能够在文件描述符的值无效时,结束 poll() 。相反,在 revents 域上使用该宏函数时,在检查 poll() 函数后,文件描述符是否有效。可用于处理网络信息时,检查 socket handler 是否已经无效。

最后一个参数 timeout 指定 poll() 将在超时前等待一个事件多长事件。这里有 3 种情况:

1) timeout 为 -1

这会造成 poll 永远等待。poll() 只有在一个描述符就绪时返回,或者在调用进程捕捉到信号时返回(在这里,poll 返回 -1),并且设置 errno 值为 EINTR 。-1 可以用宏定义常量 INFTIM 来代替(在 pth.h 中有定义) 。

2) timeout 等于0

在这种情况下,测试所有的描述符,并且 poll() 立刻返回。这允许在 poll 中没有阻塞的情况下找出多个文件描述符的状态。

3) time > 0

这将以毫秒为单位指定 timeout 的超时周期。poll() 只有在超时到期时返回,除非一个描述符变为就绪,在这种情况下,它立刻返回。如果超时周期到齐,poll() 返回 0。这里也可能会因为某个信号而中断该等待。

和 select 一样,文件描述符是否阻塞对 poll 是否阻塞没有任何影响。

代码示例:

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <poll.h>

#define NAME  "/dev/input/mouse1"

int main(void)

{

char buf[100]={0};                 //注意这里的定义的buf不能够使用全局的

//int poll(struct pollfd *fds, nfds_t nfds, int timeout);

struct pollfd a[2]={0};

int fd= open(NAME,O_RDWR);   //定义鼠标文件描述符

if(fd<0)

{

perror("open mouse");

_exit(-1);

}

//实例化结构体

a[0].fd=fd;               //鼠标

a[0].events=POLLIN;

a[1].fd=0;                 //键盘

a[1].events=POLLIN;

int ret=poll(a,fd+1,10000);

if(ret<0)

{

perror("poll");

_exit(-1);

}

if(ret==0)

{

printf("超时了");

}

else     //判断是谁发生了IO

{

if(a[0].events==a[0].revents)        //鼠标

{

memset(buf,0,sizeof(buf));

read(fd,buf,10);

printf("读出来的鼠标内容是:[%s]\n",buf);

}

if(a[1].events==a[1].revents)        //键盘

{

memset(buf,0,sizeof(buf));

read(0,buf,50);

printf("读出来的键盘内容是:[%s]\n",buf);

}

}

return 0;

}

3.6.6.异步IO

3.6.6.1、何为异步IO

(1)几乎可以认为:异步IO就是操作系统用软件实现的一套中断响应系统(有点类似与硬件中断)。

有两种类型的文件IO同步:同步文件IO和异步文件IO。异步文件IO也就是重叠IO。【在同步文件IO中,线程启动一个IO操作然后就立即进入等待状态,直到IO操作完成后才醒来继续执行。而异步文件IO方式中,线程发送一个IO请求到内核,然后继续处理其他的事情,内核完成IO请求后,将会通知线程IO操作完成了。】

如果IO请求需要大量时间执行的话,异步文件IO方式可以显著提高效率,因为在线程等待的这段时间内,CPU将会调度其他线程进行执行,如果没有其他线程需要执行的话,这段时间将会浪费掉(可能会调度操作系统的零页线程)。如果IO请求操作很快,用异步IO方式反而还低效,还不如用同步IO方式。

同步IO在同一时刻只允许一个IO操作,也就是说对于同一个文件句柄的IO操作是序列化的,即使使用两个线程也不能同时对同一个文件句柄同时发出读写操作。重叠IO允许一个或多个线程同时发出IO请求。

异步IO在请求完成时,通过将文件句柄设为有信号状态来通知应用程序,或者应用程序通过GetOverlappedResult察看IO请求是否完成,也可以通过一个事件对象来通知应用程序。

简单的说“同步在编程里,一般是指某个IO操作执行完后,才可以执行后面的操作。异步则是,将某个操作给系统,主线程去忙别的事情,等内核完成操作后通知主线程异步操作已经完成。”

(2)异步IO的工作方法是:我们当前进程向内核注册一个异步IO事件(使用signal注册一个信号SIGIO的处理函数),然后当前进程可以正常处理自己的事情,内核就去帮你完成或者说是检测你希望的事件是否发生,当异步事件发生后当前进程会收到内核传来的一个SIGIO信号(类似于中断信号)从而执行绑定的处理函数去处理这个异步事件。

3.6.6.2、涉及的函数:

(1)fcntl(F_GETFL、F_SETFL、O_ASYNC、F_SETOWN)    设置异步通知

(2)signal或者sigaction函数(SIGIO)

3.6.3.代码实践

3.6.7.存储映射IO

存储映射IO使一个磁盘文件(物理地址)与存储空间(内存地址)中的一个缓冲区相映射。于是当从缓冲区取数据,就相当于读文件中的相应字节。与此类似,将数据存入缓冲区,则相应字节就自动地写入文件。这样就可以在不使用read和write的情况下执行IO。为了使用这种功能,应首先告诉内核将一个给定的文件映射到一个存储区域中,这是由mmap函数实现的。

3.6.7.1、mmap函数:把一个磁盘文件和一个内存映射起来    内存映射函数

3.6.7.2、LCD显示和IPC之共享内存

3.6.7.3、存储映射IO的特点

(1)共享而不是复制,减少内存操作

(2)处理大文件时效率高,小文件不划算(视频用到的也比较多)

函数原型:

void *mmap(void *addr, size_t length, int prot, int flags,

int fd, off_t offset);

addr参数用于指定映射存储区的起始地址,通常将其设置为0,这表示由系统选择该映射区的起始地址,此函数的返回地址是该映射区的起始地址。

fd指定要被映射文件的描述符,在映射该文件到一个地址空间之前,先要打开该文件。

length是映射的字节数。

offset是要映射字节在文件中的起始偏移量。

prot参数说明对映射存储区的保护要求,但不能超过文件open模式访问权限,prot可选值如下:

PROT_EXEC Pages may be executed.

PROT_READ Pages may be read.

PROT_WRITE Pages may be written.

PROT_NONE Pages may not be accessed.

flags参数影响映射存储区的多种属性,其中MAP_SHARED和MAP_PRIVATE两者必须选择其一,还有许多其它的MAP_XXX是可选的。

【还有一种就是多进程下,父进程fork创建一个子进程来处理不同的事情】。

时间: 2024-08-03 17:43:13

(51)LINUX应用编程和网络编程之六Linux高级IO的相关文章

Linux程序设计学习笔记----网络编程之网络数据包拆封包与字节顺序大小端

网络数据包的封包与拆包 过程如下: 将数据从一台计算机通过一定的路径发送到另一台计算机.应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部(header),称为封装(Encapsulation),如下图所示: 不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据包(packet),在链路层叫做帧(frame).数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,最后将应用层数据交给应用程序处理. 上图对应两台计算机在同一网段中的情况,

(50)LINUX应用编程和网络编程之五 Linux信号(进程间通信)

信号实现进程间的通信 3.5.1.什么是信号 3.5.1.1.信号是内容受限(只是一个int型的数字)的一种异步通信机制 (1)信号的目的:用来通信(进程与进程之间的通信) (2)信号是异步的(对比硬件中断),信号好像就是一种软件中断. (3)信号本质上是int型数字编号(事先定义好的) 3.5.1.2.信号由谁发出 (1)用户在终端按下按键 (2)硬件异常后由操作系统内核发出信号 (3)用户使用kill命令向其他进程发出信号 (4)某种软件条件满足后也会发出信号,如alarm闹钟时间到会产生S

(46)LINUX应用编程和网络编程之一Linux应用编程框架

3.1.1.应用编程框架介绍 3.1.1.1.什么是应用编程 (1)整个嵌入式linux核心课程包括5个点,按照学习顺序依次是:裸机.C高级.uboot和系统移植.linux应用编程和网络编程.驱动. (2)典型的嵌入式产品就是基于嵌入式linux操作系统来工作的.典型的嵌入式产品的研发过程就是:第一步让linux系统在硬件上跑起来(系统移植工作),第二步基于linux系统来开发应用程序实现产品功能. (3)基于linux去做应用编程,其实就是通过调用linux的[系统API]来实现应用需要完成

XMPP-05Socket编程之网络编程篇

要学习XMPP,就要先了解Socket编程,在学习Socket之前,还要先了解一下网络编程 一.网络编程基本概念 通过使用套接字来达到进程间通信目的的编程就是网络编程. 网络编程从大的方面说就是对信息的发送到接收,中间传输为物理线路的作用,编程人员可以不用考虑…… 网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到通信的目的!中间最主要的就是数据包的组装,数据包的过滤,数据包的捕获,数据包的分析,当然最后再做一些处理

66.JAVA编程思想——网络编程

66.JAVA编程思想--网络编程 历史上的网络编程都倾向于困难.复杂,而且极易出错. 程序员必须掌握与网络有关的大量细节,有时甚至要对硬件有深刻的认识.一般地,我们需要理解连网协议中不同的"层"(Layer).而且对于每个连网库,一般都包含了数量众多的函数,分别涉及信息块的连接.打包和拆包:这些块的来回运输:以及握手等等.这是一项令人痛苦的工作.但是,连网本身的概念并不是很难.我们想获得位于其他地方某台机器上的信息,并把它们移到这儿:或者相反.这与读写文件非常相似,只是文件存在于远程

iOS网络编程开发—网络编程基础

iOS网络编程开发—网络编程基础 一.网络编程 1.简单说明 在移动互联网时代,移动应用的特征有: (1)几乎所有应用都需要用到网络,比如QQ.微博.网易新闻.优酷.百度地图 (2)只有通过网络跟外界进行数据交互.数据更新,应用才能保持新鲜.活力 (3)如果没有了网络,也就缺少了数据变化,无论外观多么华丽,终将变成一潭死水 移动网络应用 = 良好的UI + 良好的用户体验 + 实时更新的数据 新闻:网易新闻.新浪新闻.搜狐新闻.腾讯新闻 视频:优酷.百度视频.搜狐视频.爱奇艺视频 音乐:QQ音乐

linux服务端的网络编程

常见的Linux服务端的开发模型有多进程.多线程和IO复用,即select.poll和epoll三种方式,其中现在广泛使用的IO模型主要epoll,关于该模型的性能相较于select和poll要好不少,本文也主要讨论该模型而忽略另外两种IO复用模型. 多线程相较于多进程开销比较小,但是要主要主线程往子线程传递数据的时候要注意变量互斥访问来保证线程安全. epoll模型在Linux2.6内核中引入的,改进了select中的一些明显设计上的缺点,具有更高的效率.主要体现在以下几个方面: 1. epo

Linux下的socket网络编程

linux 网络编程是通过socket(套接字)接口实现,Socket是一种文件描述符,socket起源于UNIX,在Unix一切皆文件哲学的思想下,socket是一种"打开-读/写-关闭"模式的实现,服务器和客户端各自维护一个"文件",在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件. socket 类型 常见的socket有3种类型如下.     (1)流式socket(SOCK_STREAM )     流式套接字提供可靠

linux下简单socket网络编程

在进行socket网络编程时, 我们需要了解一些必备的知识,例如什么是socket,ipv4的地址结构,套接字类型等等,不然上来直接看代码就会晕,当初学习网络编程时,看书上的例子,总有感觉书上讲的都很简要.再或者讲的原理太多把人绕晕.我这里只想让大家简单知道怎么使用socket进行网络编程并且给出的例子可以直接使用参考. 1. 什么是socket (1) socket 可以看成是用户进程与网络协议栈的编程接口.就是说应用层可以看成是用户进程,传输层网络层数据链路层看成网络协议栈,因为这三个层的传