`

Select代码理解

 
阅读更多

Socket代码理解

1 socket select流程

(1)初始化server socket

initServerSocket

(2)监管 server socket

FD_SET ( gehServerFd, &readFdsMaster );

(3)更新socket fd最大值

UPDATE_MAXFD ( gehServerFd );

(4)循环等待数据

while ( 1 )

rv = select ( maxFdTmp + 1, &readFdsMasterTmp, NULL, NULL, NULL );

(5)select三种返回值的判断

(6)检测是哪个fd有数据

if ( !FD_ISSET ( actualFd, &readFdsMasterTmp ) )

(7)两种情况:server socket有新连接或者client socket有数据可读

if ( actualFd == gehServerFd )

if ( actualFd != gehServerFd )

(8)server socket有新连接,则accept并监管和更新fd最大值

if ( 4 > ( connFd = accept ( gehServerFd, ( SA * ) & cliAddress, &sockAddressLen ) ) )

FD_SET ( connFd, &readFdsMaster );

UPDATE_MAXFD ( connFd );

(9)client socket有新数据,则接收

ehRead

2 select关键点

two match

(1).fd_set in select match fd_set in FD_ISSET

It can be changed in select

(2).maxfd in select match maxfd in for

It can be changed in listenfd

3 KEEP Alive

底层实现,AP层不用关心

tcmRet initKeepAlive()

{

system("echo 10 > /proc/sys/net/ipv4/tcp_keepalive_time");

system("echo 2 > /proc/sys/net/ipv4/tcp_keepalive_intvl");

system("echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes");

return TCMRET_SUCCESS;

}

tcmRet setKeepAlive( int kvFd )

{

int keepAliveFlag = 1;

int ret;

ret = setsockopt(kvFd,SOL_SOCKET,SO_KEEPALIVE,(void *)&keepAliveFlag,sizeof(keepAliveFlag));

return ( (ret == 0) ? TCMRET_SUCCESS:TCMRET_FAILURE );

}

4 Error check

不仅仅是check error,并且还有clear error的作用。

getsockopt ( actualFd, SOL_SOCKET, SO_ERROR, &error, ( socklen_t * ) &errlen );

if( error == -1 )

{

tcmLog_debug( "Before accept actualFd == gehServerFd This socket %d is error no is %d errlen is %d, /

so we donot accept it", actualFd, error, errlen );

continue;

}

5 read 和write结构体数据

注意tail部数据的读取或发送

typedef struct EHOMEPROTOCOLMSG

{

uint16_t protocolVersion;

uint16_t payloadLen;

uint8_t reserve[16];

/**************Overhead is the message header*******************/

uint16_t eventType;

uint16_t valueLen;

}EhomeProtocolMsg;

tcmRet ehRead ( int rdFd, EhomeProtocolMsg** rdBuf, unsigned int rdTimeout )

{

tcmLog_debug ( "Start fd read message" );

EhomeProtocolMsg* msgTmp;

int rc;

tcmRet ret;

if ( rdBuf == NULL )

{

return TCMRET_INVALID_PARAMETER;

}

else

{

*rdBuf = NULL;

}

msgTmp = ( EhomeProtocolMsg * ) malloc ( sizeof ( EhomeProtocolMsg ) );

if ( msgTmp == NULL )

{

return TCMRET_INTERNAL_ERROR;

}

rc = read ( rdFd, msgTmp, sizeof ( EhomeProtocolMsg ) );

printf( "First read header data length is %d", rc );

if ( ( rc == 0 ) ||

( ( rc == -1 ) && ( errno == 131 ) ) ) /* new 2.6.21 kernel seems to give us this before rc==0 */

{

printf( "First read rc == -1 or 0/n" );

/* broken connection */

free ( msgTmp );

return TCMRET_DISCONNECTED;

}

else if ( rc < -1 || rc != sizeof ( EhomeProtocolMsg ) )

{

printf( "First read rc < -1/n" );

free ( msgTmp );

return TCMRET_DISCONNECTED;

}

uint16_t valueLenTmp = msgTmp->valueLen;

msgTmp->valueLen = ntohs(valueLenTmp);

if ( msgTmp->valueLen > 0 )

{

int totalReadSoFar = 0;

int totalRemaining = msgTmp->valueLen;

char *inBuf;

/* there is additional data in the message */

msgTmp = ( EhomeProtocolMsg * ) realloc ( msgTmp, sizeof ( EhomeProtocolMsg ) + /

msgTmp->valueLen );

if ( msgTmp == NULL )

{

free ( msgTmp );

return TCMRET_INTERNAL_ERROR;

}

inBuf = ( char * ) ( msgTmp + 1 );

while ( totalReadSoFar < msgTmp->valueLen )

{

rc = read ( rdFd, inBuf, totalRemaining );

printf( "Second read data length is %d/n", rc );

if ( ( rc == 0 ) ||

( ( rc == -1 ) && ( errno == 131 ) ) )

{

printf( "Second read rc == 0 or -1/n" );

free ( msgTmp );

return TCMRET_DISCONNECTED;

}

else if ( rc < -1 )

{

printf( "Second read rc < -1 /n" );

free ( msgTmp );

return TCMRET_DISCONNECTED;

}

else

{

inBuf += rc;

totalReadSoFar += rc;

totalRemaining -= rc;

}

}

}

/**************************Hex printf**************************/

tcmLog_debug( "Read HEX buf from socket fd %d", rdFd );

if( (sizeof ( EhomeProtocolMsg ) + msgTmp->valueLen) < 200 )

dump( msgTmp, sizeof ( EhomeProtocolMsg ) + msgTmp->valueLen );

/***************************************************************/

*rdBuf = msgTmp;

return TCMRET_SUCCESS;

}

tcmRet ehWrite ( int wtFd, EhomeProtocolMsg* wtBuf )

{

unsigned int totalLen;

int rc;

tcmRet ret = TCMRET_SUCCESS;

uint16_t valueLenTmp = ntohs(wtBuf->valueLen);

totalLen = sizeof ( EhomeProtocolMsg ) + valueLenTmp;

/**************************Hex printf******************************/

tcmLog_debug( "Write HEX buf to socket fd %d", wtFd );

if( totalLen < 200 )

dump( wtBuf, totalLen );

/*******************************************************************/

rc = write ( wtFd, ( char * ) wtBuf, totalLen );

if ( rc < 0 )

{

if ( errno == EPIPE )

{

/*

* This could happen when smd tries to write to an app that

* has exited. Don't print out a scary error message.

* Just return an error code and let upper layer app handle it.

*/

return TCMRET_DISCONNECTED;

}

else

{

ret = TCMRET_INTERNAL_ERROR;

}

}

else if ( rc != ( int ) totalLen )

{

ret = TCMRET_INTERNAL_ERROR;

}

return ret;

}

6 十六进制的输出

将read和write的数据,均以十六进制的格式输出

void dtoh(uint8_t * hex,uint8_t n)

{

static const uint8_t HEX[] = "0123456789ABCDEF";

hex[0] = HEX[n / 16];

hex[1] = HEX[n % 16];

}

void dump_block(char * in,char * out,int len)

{

int cur;

for (cur = 0; cur < len; cur++)

{

dtoh(out + 2 * cur,in[cur]);

}

}

void hex_disp(char * in,int len,int size)

{

int cur = 0;

int row_cnt = 0;

//tcmLog_debug("%08dh:",row_cnt++);

char* bufTmp = (unsigned char *)malloc(len * 4 + 1);

memset( bufTmp , 0, len*4 + 1 );

char* pbufTmp = bufTmp;

do

{

sprintf( pbufTmp + strlen( bufTmp ) ,"%-3.2s " ,in + size * cur);

cur++;

if (cur % 8 == 0)

{

//tcmLog_debug("/n%08dh:",row_cnt++);

}

}

while(cur < len);

pbufTmp[strlen(bufTmp)]='/0';

tcmLog_debug( "%s", pbufTmp );

free(bufTmp);

}

#ifdef _NOT_PRINTF_HEX_

void dump (char * in,int len)

{

unsigned char * out = (unsigned char *)malloc(len * 2 + 1);

dump_block(in,out,len);

hex_disp(out,len,2);

free(out);

}

#endif

#ifndef _NOT_PRINTF_HEX_

void dump (char * in,int len)

{

}

#endif

7 测试程序

http://download.csdn.net/source/3119181

分享到:
评论

相关推荐

    Pytorch中index_select() 函数的实现理解

    主要介绍了Pytorch中index_select() 函数的实现理解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    javascript 操作表单select的常用步骤

    javascript 操作表单select的常用步骤,删除,添加,修改 用代码实现,一看就明白理解用法

    HTML select option基础理解及使用

    复制代码代码如下: var e = document.getElementById(“selectId”); e. options= new Option(“文本”,”值”) ; //创建一个option对象,即在&lt;select&gt;标签中创建一个或多个”值”&gt;文本&lt;/option&gt; //options是个...

    linux 下socket通信中select的用法实例

    可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件...

    使用c:forEach模拟s:select标签

    这是一份让你可以理解JavaWeb开发中如何使用struts2对下拉列表数据初始化,对于初学Struts2的同学是非常不错的入门代码实例,并且有助于理解struts里的select标签与c:forEach标签之间的关系。

    深入理解Antd-Select组件的用法

    主要介绍了深入理解Antd-Select组件的用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    【数据库】作业6——SQL练习3 – SELECT(单表查询)

    2. 写出自己的理解/收获/心得体会(部分比较复杂的例题,建议增加测试方法和测试数据,举一反三)。 REF:建表&插入数据 作业原地址:作业 书接上回:【数据库】作业5——SQL练习2 – INDEX / INSERT / SELECT 注:...

    解决 Ie 6下 select挡住div的通用函数

    @version 1.0.0 */ function topDiv(divId,iframeId) &lt;br&gt; 在IE中,select属于window类型控件,它会“挡住”所有非window类型控件 可以这么理解,div这样的组件是在浏览器客户区使用代码“渲染”的,...

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    该资料是《Oracle SQL高级编程》的源代码 对应的书籍资料见: Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐) 基本信息 原书名: Pro Oracle SQL 原出版社: Apress 作者: (美)Karen Morton Kerry ...

    理解golang中关键字-chan&select

    chan channel直译过来就是管道,chan关键字定义了goroutine中的管道通信,一个goroutine可以和另一个goroutine进行通信。 chan的读写和定义如下: //define a chan type variable ...看下面这段代码,其中x获

    TCP协议socke套接字(服务端&客户端)网络协议配置代码

    网络套接字(socket)编程,深入理解TCP、UDP协议;用select网络框架,写一个简单的C/S程序,可以正常运行。此代码是我用来记录学习网络套接字的过程,代码是在linux操作系统的vim界面下基于C++编写的,如果在VS或者...

    mysql查询语句汇总基本语法.doc

    这些语句将帮助您更好地理解和使用MySQL数据库。 一、基本SELECT查询 SELECT语句用于从数据库中选择数据。其基本语法如下: sql复制代码 SELECT column1, column2, ... FROM table_name; 例如,从一个名为...

    js select option对象小结

    一基础理解: var e = document.getElementById(“selectId”); e. options= new Option(“文本”,”值”) ; //创建一个option对象,即在&lt;select&gt;标签中创建一个或多个”值”&gt;文本&lt;/option&gt; //options是个...

    javascript对select标签的控制(option选项/select)

    javascript对它们的操作 一、基础理解 代码如下: var e = document.getElementById(“selectId”); e. options= new Option(“文本”,”值”) ; //创建一个option对象,即在&lt;select&gt;标签中创建一个或多个”值...

    CARS_波长选择_CARS特征波长_rubbed1st_cars_

    可以很好的进行波长的选择,代码特别完整,一旦参数选定,结果就稳定下来,不再混入随机。在原来版本上加入自己理解改写,使得代码更容易理解,can select wavelengths

    用SQL实现统计报表中的小计与合计的方法详解

     优点:实现代码简洁,要求对GROUPPING和ROLLUP很深的理解。 缺点:低版本的Sql Server不支持。2.游标实现。 优点:思路逻辑简洁。 缺点:复杂和低效。3.利用临时表。 优点:思路逻辑简洁,执行效率高。SQL实现...

    mysql 源码分析+mysql-5.0.18的源码

    主要介绍Mysql主要的调用流程,将从代码的角度来看一个从用户发出的"select * from test" SQL命令在服务器内部是如何被执行的。从我个人的经验来看,阅读理解大规模项目的代码最重要的两个方面,一是了解主要的数据...

    套接字I/O模式的服务端客户通信的程序源代码

    套接字编程的实例,可执行,便于理解select模型及EVENT模型的基本原理

    net学习笔记及其他代码应用

    解2: select top 10 * from A where id &gt; (select max(id) from (select top 30 id from A )as A) 34.面向对象的语言具有________性、_________性、________性 答:封装、继承、多态。 35.能用foreach遍历访问的...

Global site tag (gtag.js) - Google Analytics