socket编程简述 - 十年扬州梦,青楼薄幸名 - C 博客

来源:百度文库 编辑:神马文学网 时间:2024/04/24 05:31:02
socket编程简述
这几天被我所维护的一个程序的小bug困扰着, 这个程序在中移动现网上很多机器跑着呢. 在solaris5.7, solaris,Linux等上面是没有问题的, 而在solaris5.10上却莫名其妙地产生死循环,  我能定位到错误的地方, 却说不出原因,也没有用<>里作者的惯用手法----抓包, 来观察tcp包的交互,  有时间再去查错吧.
不过在验证错误期间, 自己写了个tcpserver程序:
非阻塞socket, select模型
/**
*@file  tcpserver.c
*
*@brief tcpserver.
*
*@author liangb
*@date  2007-06-07
*@version 1.0
*$Id: tcpserver.c,v 1.0 2007/06/07 14:10:56 liangb Exp $
*/
#ifdef linux
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//---------------------------The macro definition-------------------------------
#define MODULE_NAME    "tcpserver"
//---------------------------The variable definition----------------------------
int miPort = 8080;
char msIpAddr[ 128 ] = "127.0.0.1";
//---------------------------The function prototype-----------------------------
//---------------------------The function definition----------------------------
// The main function
int main( int argc, char ** argv )
{
char ch = 0;
struct sockaddr_in servaddr;
int liListenSock = 0;
struct sockaddr_in cliaddr;
socklen_t clilen = 0;
int connfd = 0;
int maxfdp1 = 0;
fd_set rset;
fd_set rsetTemp;
struct timeval timeout;
int liRet = 0;
int connfds[ 1024 ];
int n = 0;
int liRecvLen = 0;
char lsRecvBuf[ 1024 ] = "";
// get the option
while( ( ch = getopt( argc, argv, "p:h:v" ) ) != EOF ) {
switch( ch ) {
case ‘p‘:
// port
miPort = atoi( optarg );
break;
case ‘h‘:
// host address
strncpy( msIpAddr, optarg, sizeof( msIpAddr ) - 1 );
break;
case ‘v‘:
default:
printf( "\n" );
printf( "Usage: tcpserver [-h ipaddress] [-p port] [-v] [-h]\n" );
printf( "\t -h ip address, default is 127.0.0.1\n" );
printf( "\t -p port, default is 8080\n" );
printf( "\t -v print the help\n" );
printf( "\n" );
exit( 1 );
}
}
// socket listen
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(miPort);
servaddr.sin_addr.s_addr = inet_addr(msIpAddr);
liListenSock = socket(AF_INET, SOCK_STREAM, 0);
if( 0 > liListenSock ) {
printf( "socket init fail: errno=%d\n", errno );
return 1;
}
if(0 > bind(liListenSock, (const struct sockaddr * )&servaddr, sizeof(servaddr))) {
printf( "socket bind fail: errno=%d\n", errno );
return 1;
}
if(0 > listen(liListenSock, 200)) {
printf( "socket listen fail: errno=%d\n", errno );
return 1;
}
memset( &connfds, 0, sizeof( connfds ) );
maxfdp1 = liListenSock + 1;
FD_ZERO(&rsetTemp);
FD_SET(liListenSock, &rsetTemp);
while( 1 ) {
memcpy( &rset, &rsetTemp, sizeof(fd_set));
timeout.tv_sec = 1;///1 seconds
timeout.tv_usec = 0;
liRet = select(maxfdp1, &rset, NULL, NULL, &timeout);
if( 0 >= liRet ) {
continue;
}
printf( "select(): liRet=%d\n", liRet );
if( FD_ISSET( liListenSock, &rset ) ) {
// accept socket
connfd = accept(liListenSock, (struct sockaddr *)&cliaddr, &clilen);
if( 0 >= connfd ) {
continue;
}
fcntl( connfd, F_SETFL, O_NONBLOCK | fcntl( connfd, F_GETFL, 0 ) );
if( maxfdp1 <= connfd ) {
maxfdp1 = connfd + 1;
}
FD_SET( (unsigned int)connfd, &rsetTemp );
connfds[ connfd ] = connfd;
printf( "sock connect OK, connfd=%d\n", connfd );
} else {
// recv data
for( n = 1; n < sizeof( connfds ) / sizeof( int ) && liRet > 0; ++n ) {
if( connfds[ n ] > 0 && FD_ISSET( connfds[n], &rset) ) {
do {
memset( lsRecvBuf, 0, sizeof( lsRecvBuf ) );
liRecvLen = recv( connfds[ n ], lsRecvBuf, sizeof( lsRecvBuf ) - 1, 0 );
if( 0 == liRecvLen ) {
// socket is closed
printf( "connsock is closed, connfd=%d, errno=%d, liRecvLen=0\n",
connfds[ n ], errno );
FD_CLR( (unsigned int)connfds[ n ], &rsetTemp );
close( connfds[ n ] );
connfds[ n ] = 0;
break;
} else if( 0 > liRecvLen ) {
if( errno == EWOULDBLOCK || errno == EAGAIN ) {
// would block
printf( "would block, errno=%d, connfd=%d, liRecvLen=%d\n",
errno, connfds[ n ], liRecvLen );
} else {
// socket error
printf( "socket err, errno=%d, connfd=%d, liRecvLen=%d\n",
errno, connfds[ n ], liRecvLen );
FD_CLR( (unsigned int)connfds[ n ], &rsetTemp );
close( connfds[ n ] );
connfds[ n ] = 0;
}
break;
} else {
// recv data success
lsRecvBuf[ liRecvLen ] = ‘\0‘;
printf( "recv OK, connfd=%d, liRecvLen=%d, data: %s\n",
connfds[ n ], liRecvLen, lsRecvBuf );
if( ‘\n‘ == lsRecvBuf[ liRecvLen - 1 ] ) {
break;
}
}
} while( 1 );
liRet--;
}
}
}
}
return 0;
}
编译: solaris系统
# make tcpserver
CC   = gcc
RM   = rm -f
CFLAGS  = -g -Wall
LIBS    = -lsocket -lnsl
TARGET  = tcpserver
# make all
all: $(TARGET)
@exit 0
# make tcpserver
tcpserver: tcpserver.c
$(CC) $(CFLAGS) $^ -o $@ $(LIBS)
# implicit rules
.c.o:
$(CC) -c $(CFLAGS) $<
# clean the temp file
.PHONY: clean
clean:
$(RM) $(TARGET) core *.o *.log
posted on 2007-06-10 20:33梁-兄 阅读(285)评论(2)  编辑 收藏引用

# re: socket编程简述2007-06-11 10:08
solaris5.10上错误是什么呢?为什么不贴出来?  回复  更多评论
# re: socket编程简述2007-06-11 23:44
What‘s wrong? Please paste it.  回复  更多评论