Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3949344
  • 博文数量: 930
  • 博客积分: 12070
  • 博客等级: 上将
  • 技术积分: 11447
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-15 16:57
文章分类

全部博文(930)

文章存档

2011年(60)

2010年(220)

2009年(371)

2008年(279)

分类: LINUX

2010-04-12 19:41:57

nonblock_socket.c
 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif

#include "common.h"
/*
s - socketfd
sec - timeout seconds
usec - timeout microseconds
x - select status(read write error)
*/

int net_select(int s, int sec, int usec, short x)
{
 int st = errno;
 struct timeval to;
 fd_set fs;
 to.tv_sec = sec;
 to.tv_usec = usec;
 FD_ZERO(&fs);
 FD_SET(s, &fs);
 switch(x){
  case READ_STATUS:
    st = select(s+1, &fs, 0, 0, &to);
    break;
  case WRITE_STATUS:
    st = select(s+1, 0, &fs, 0, &to);
    break;
  case EXCPT_STATUS:
    st = select(s+1, 0, 0, &fs, &to);
    break;
  default:
      break;
 }
 return(st);
}

int tcp_connect(const char *host, const unsigned short port)
{
  unsigned long non_blocking = 1;
  unsigned long blocking = 0;
  int ret = 0;
  char * transport = "tcp";
  struct hostent *phe; /* pointer to host information entry */
  struct protoent *ppe; /* pointer to protocol information entry*/
  struct sockaddr_in sin; /* an Internet endpoint address */
  int s; /* socket descriptor and socket type */
  int error;
    
  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  if ((sin.sin_port = htons(port)) == 0)
   {
        DEBUG("invalid port \"%d\"\n", port);
     exit(1);
    }
  /* Map host name to IP address, allowing for dotted decimal */
  if ( phe = gethostbyname(host) )
     memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
  else if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE )
     {
         DEBUG("can't get \"%s\" host entry\n", host);
      exit(1);
     }
     
  /* Map transport protocol name to protocol number */
  if ( (ppe = getprotobyname(transport)) == 0)
    {
        DEBUG("can't get \"%s\" protocol entry\n", transport);
      exit(1);
     }
     
  /* Allocate a socket */
  s = socket(PF_INET, SOCK_STREAM, ppe->p_proto);
  if (s < 0)
   {
        DEBUG("can't create socket: %s\n", strerror(errno));
     exit(1);
    }
  /* Connect the socket with timeout */
  ioctl(s,FIONBIO,&non_blocking);

  //fcntl(s,F_SETFL, O_NONBLOCK);

  if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
   {
    struct timeval tv;
    fd_set writefds;
    fd_set readfds;
         
    // 设置连接超时时间

    if( EINPROGRESS)
      goto error_ret;
            
    tv.tv_sec = 10; // 秒数

    tv.tv_usec = 0; // 毫秒

        FD_ZERO(&writefds);
        FD_SET(s, &writefds);
        readfds = writefds;
        if(select(s+1,&readfds,&writefds,NULL,&tv) != 0)
         {
            if(FD_ISSET(s,&writefds)||FD_ISSET(s,&readfds))
             {
                int len=sizeof(error);
                //下面的一句一定要,主要针对防火墙

                if(getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&error, &len) < 0)
                    goto error_ret;
                if(error != 0)
                    goto error_ret;
             }
            else
                goto error_ret; //timeout or error happen

         }
        else
             goto error_ret;
 
      goto ok_ret;
    }
   else
    goto ok_ret;
       
error_ret:
  close(s);
  DEBUG("can't connect to %s:%d\n", host, port);
  exit(1);
ok_ret:
     DEBUG("%s", "nonblock connect over\n");
     ioctl(s,FIONBIO,&blocking);
   return s;
}
 

 

调用:


 

fd = tcp_connect(i_host, i_port);
    if(net_select(fd, 0, 500, WRITE_STATUS)>0){
        /* send off the message */
        http = get_dangdang(buf1);
        send(fd, http, strlen(http),0);
    }
    else{
        DEBUG("Socket I/O Write Timeout %s:%s\n", i_host, i_port);
        exit(1);
    }
     
    if(net_select(fd, 2, 0, READ_STATUS)>0)
     {
      /* display the server response */
      DEBUG("%s", "Server response:\n");
      while((n = recv(fd, buf, MAX_BUF_LEN,0))>0)
       { 
        buf[n]='\0';

        }
     }
    else
     {
       DEBUG("Socket I/O Read Timeout %s:%s\n", i_host, i_port);
       exit(1);
     }


阅读(1309) | 评论(0) | 转发(0) |
0

上一篇:time

下一篇:常用的Linux快捷键

给主人留下些什么吧!~~