北京素菜馆排行榜:socket编程简述 - 十年扬州梦,青楼薄幸名 - C 博客

来源:百度文库 编辑:中财网 时间:2024/04/28 06:43:45

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:08yuadam

solaris5.10上错误是什么呢?为什么不贴出来?  回复  更多评论  

# re: socket编程简述2007-06-11 23:44stevenliu

What‘s wrong? Please paste it.  回复  更多评论