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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值