SOCKET例子

本文介绍了一个基于TCP的非阻塞Select机制的服务端与客户端实现案例,通过对核心代码的解析,展示了如何利用socket编程进行多连接并发处理,并详细说明了服务端与客户端的具体操作流程。

* name: tcp_slct.c
* written by saodrin zhang for test
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SVC_PORT        9999
int main_serv(int argc, char *argv[]);
int main_clnt(int argc, char *argv[]);
int main(int argc, char *argv[])
{
    int ret;
    if (argc == 1)
        ret = main_serv(argc, argv);
    else
        ret = main_clnt(argc, argv);
    return ret;
}
#define MAX_CNCT_NUM 8
#define BUF_SIZE 256
int main_serv(int argc, char *argv[])
{
    int ret, i, k, n;
    int len;
    int inp_fd, sockfd, cnctfd, maxfd;
    int cepfd[MAX_CNCT_NUM], cepnum, entry; /* clntfd[], clntnum */
    int optval, sndFlag;
    fd_set readfds, writefds;
    struct sockaddr_in bindaddr;  //servaddr
    struct sockaddr_in cnctaddr;  //clntaddr
    struct timeval timeout;
    char text[BUF_SIZE], buf[BUF_SIZE];
    char sBuf[MAX_CNCT_NUM][BUF_SIZE];
    maxfd = 0;
    /*inp_fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);*/
    inp_fd = fileno(stdin);
    printf("Inp_fd is %d/n", inp_fd); /* assert(inp_fd >= 0); */
    fcntl(inp_fd, F_SETFL, fcntl(inp_fd, F_GETFL) | O_NONBLOCK);
    /* assign the Protocol Family for communication */
    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        printf("socket create error!/n");
        return -1;
    }
    memset(&bindaddr, 0, sizeof(struct sockaddr_in));
    /* AF_INET: Address Family */
    bindaddr.sin_family = AF_INET;
    /* INADDR_ANY: address of any interface owned by the host */
    bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    bindaddr.sin_port = htons(SVC_PORT);
    bzero(&(bindaddr.sin_zero), 8); /*  */
    /* 置 socket 重新使用  */
    optval = 1; /* option enable */
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof(optval)) = 0)
    {
        fcntl(inp_fd, F_SETFL, O_NONBLOCK);
    }
    if (sockfd >= 0)
    {
        fcntl(sockfd, F_SETFL, O_NONBLOCK);
    }
    text[0] = '/0';
    for (i = 0; i = 0)
        {
            FD_SET(sockfd, &readfds);
            maxfd = sockfd > maxfd ? sockfd : maxfd;
        }
        for (i = 0, n = 0; i  0)
            {
                FD_SET(cepfd, &readfds);
                if (sBuf[0] != '/0')
                {
                    /* printf("WR: FD_SET.../n"); */
                    FD_SET(cepfd, &writefds);
                }
                maxfd = cepfd > maxfd ? cepfd : maxfd;
                n++;
            }
        }
        ret = select(maxfd+1, &readfds, &writefds, NULL, &timeout);
        //select error when ret = -1
        if (ret == -1) printf("select error!/n");
        //time out when ret = 0
        //if (ret == 0) printf("select time out./n");
        //data coming when ret>0
        if (ret > 0)
        {
            if (FD_ISSET(inp_fd, &readfds))
            {
                /*i = read(inp_fd, &ch, 1);
                if('/n' == ch) continue;
                else printf("Input is %c/n", ch);*/
                n = read(inp_fd, text, BUF_SIZE);
                if (n >= 0)
                {
                    i = 0;
                    k = 0;
                    while (i %d: Connection from %s:%d/n", ++cepnum, /
                           inet_ntoa(cnctaddr.sin_addr), cnctaddr.sin_port);
                    fcntl(cnctfd, F_SETFL, O_NONBLOCK);
                    cepfd[entry] = cnctfd; /* client fd */
                    for (i = 0; i  0 && FD_ISSET(cepfd, &readfds))
                {
                    n = read(cepfd, buf, BUF_SIZE);
                    if (n > 0)
                    {
                        buf[n] = '/0';
                        printf("RD cepfd[%d]: %s", i, buf);
                        k++;
                        if (buf[0] != '/0' && text[0] != '/0')
                        {
                            sprintf(sBuf, "%s + ", text);
                            strcat(sBuf, buf);
                        }
                    }
                    else if (n == 0)
                    {
                        printf("RD cepfd[%d]: peer is closed./n", i);
                        shutdown(cepfd, SHUT_RDWR);
                        cepfd = -1;
                        close(cepfd);
                        cepnum--;
                    }
                    else
                    {
                        switch (errno)
                        {
                        case EAGAIN:
#if EWOULDBLOCK != EAGAIN
                        case EWOULDBLOCK:
#endif
                            k++;
                            break;
                        case EINTR:
                            /* we were stopped _before_ we had a connection */
                        case ECONNABORTED: /* this is a FreeBSD thingy */
                            /* we were stopped _after_ we had a connection */
                            k++;
                            break;
                        case EMFILE: /* out of fds */
                            k++;
                            break;
                        default:
                            perror("read");
                            cepfd = -1;  /* close it */
                            cepnum--;
                            break;
                        } /* end switch (errno) */
                    } /* end if (n > 0) */
                } /* end if (cepfd > 0 && FD_ISSET(cepfd, &readfds)) */
            } /* end for (...; i  0 && FD_ISSET(cepfd, &writefds))
                {
                    len = strlen(sBuf);
                    n = write(cepfd, sBuf, len);
                    if (n > 0) /* assert(n == len); */
                    {
                        printf("WR cepfd[%d]: %s", i, sBuf);
                        k++;
                        sBuf[0] = '/0';
                    }
                    else if (n == 0)
                    {
                        printf("WR cepfd[%d]: peer is closed.", i);
                        cepfd = -1;
                        cepnum--;
                        sBuf[0] = '/0';
                    }
                    else /* error */
                    {
                        switch (errno)
                        {
                        case EAGAIN:
#if EWOULDBLOCK != EAGAIN
                        case EWOULDBLOCK:
#endif
                            k++;
                            break;
                        case EINTR:
                            /* we were stopped _before_ we had a connection */
                        case ECONNABORTED: /* this is a FreeBSD thingy */
                            /* we were stopped _after_ we had a connection */
                            k++;
                            break;
                        case EMFILE: /* out of fds */
                            k++;
                            break;
                        default:
                            perror("read");
                            cepfd = -1;  /* close it */
                            cepnum--;
                            break;
                        } /* end switch (errno) */
                    } /* end if (n > 0) */
                } /* end if (cepfd > 0 && FD_ISSET(cepfd, &readfds)) */
            } /* end for (...; i  0) */
    }
    return 0;
}
int main_clnt(int argc, char *argv[])
{
    int ret, i, n;
    int len;
    int inp_fd, sockfd, cnctfd, maxfd;
    int cepfd[MAX_CNCT_NUM], cepnum, entry;
    int optval, sndFlag;
    fd_set readfds, writefds;
    struct sockaddr_in bindaddr;   //local client address
    struct sockaddr_in cnctaddr;   //remote server address
    struct timeval timeout;
    struct hostent    *host;
    struct in_addr servAddr;
    unsigned long servIP;
    char text[BUF_SIZE], buf[BUF_SIZE];
    if (argc h_addr_list[0], sizeof(struct in_addr));
        servIP = ntohl(servAddr.s_addr);
        printf("destIP = 0x%x/n", servIP);
    }
    else
    {
        printf("Error: gethostbyname/n");
        return -1;
    }
    /*inp_fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);*/
    inp_fd = fileno(stdin);
    printf("Inp_fd is %d/n", inp_fd); /* assert(inp_fd >= 0); */
    fcntl(inp_fd, F_SETFL, fcntl(inp_fd, F_GETFL) | O_NONBLOCK);
    maxfd = inp_fd;
    /* assign the Protocol Family for communication */
    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        printf("socket create error!/n");
        return -1;
    }
    memset(&bindaddr, 0, sizeof(struct sockaddr_in));
    /* AF_INET: Address Family */
    bindaddr.sin_family = AF_INET;
    /* INADDR_ANY: address of any interface owned by the host */
    bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    bindaddr.sin_port = htons(SVC_PORT);
    bzero(&(bindaddr.sin_zero), 8); /*  */
    /* 置 socket 重新使用  */
    optval = 1; /* option enable */
    //if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof(optval))  maxfd ? cnctfd : maxfd;
    while (1)
    {
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);
        FD_SET(inp_fd, &readfds);
        FD_SET(cnctfd, &readfds);
        if (sndFlag != 0) FD_SET(cnctfd, &writefds);
        ret = select(maxfd+1, &readfds, &writefds, NULL, &timeout);
        //select error when ret = -1
        if (ret == -1) printf("select error/n");
        //time out when ret = 0
        //if (ret == 0) printf("select time out/n");
        //data coming when ret>0
        if (ret > 0)
        {
            if (FD_ISSET(inp_fd, &readfds))
            {
                /*i = read(inp_fd, &ch, 1);
                if('/n' == ch) continue;
                else printf("Input is %c/n", ch);*/
                n = read(inp_fd, text, BUF_SIZE);
                if (n >= 0)
                {
                    text[n] = '/0';
                }
                else
                {
                    printf("RD STDIN error!/n");
                    text[0] = '/0';
                }
                if ('/n' == text[0]) continue;
                else printf("Inputed: %s", text);
                if ('q' == text[0]) break;
                else sndFlag = 1;
            }
            if (FD_ISSET(cnctfd, &readfds))
            {
                n = recv(cnctfd, buf, BUF_SIZE, MSG_DONTROUTE);
                if (n > 0)
                {
                    buf[n] = '/0';
                    printf("Recv OK: %s", buf);
                }
                else if (n == 0) /* peer is closed */
                {
                    printf("Peer is closed .../n");
                    shutdown(cnctfd, SHUT_RDWR);
                    close(cnctfd);
                    break;
                }
                else
                {
                    printf("Recv error!/n");
                }
            }
            if (FD_ISSET(cnctfd, &writefds))
            {
                if ((n = strlen(text)) > 0)
                {
                    if ((i = send(cnctfd, text, n, MSG_DONTROUTE)) != n)
                    {
                        printf("Try to send again.../n");
                        sndFlag = 1;
                    }
                    else
                    {
                        printf("Send OK: %s", text);
                        sndFlag = 0;
                    }
                }
                else
                {
                    sndFlag = 0; /* FD_CLR(cnctfd, &writefds); */
                    printf("Nothing to be sent/n");
                    if ((i = write(cnctfd, ".../n", 4)) != 4)
                        perror("Test write");
                } /* end if ((n = strlen(text)) > 0) */
            } /* end if (FD_ISSET(cnctfd, &writefds)) */
        } /* end if (ret > 0) */
    } /* end while (1) */
    return ret;
}
               

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define MaxRecvLen 500

//定义网站结构
struct DOMAIN
{
char url[255]; //http://www.xh88.com:80/index.php 完整网址
char host[20]; //www.xh88.com 主机地址
int port; //sock 联接的端口号
};
typedef struct DOMAIN domain;

int main(int argc,char *argv[])
{

//******************* 有关 sock 的变量 *************************

int sock_id; //sock 联接句柄

struct hostent *hostbyname; //主机的信息 结构
struct sockaddr_in remote_addr; //包含远端主机IP地址和端口号的结构


//******************* 有关 无阻塞 select 所用到 的变量 *************************

struct timeval timeout; //用于无阻塞 select 调用 的时间变量
fd_set sockid_readable; //sock 类似联接句柄 传递给 select 有效的连接

domain web_domain; //定义一个 web domain 的结构

char send_str[255]; //保存要发送的字符串
char *tempStr,*recBuf; //临时字串,接收到的字串指针

int recv_numb; //保存远端返回的字串大小
FILE *fp; //文件指针,用于保存从远端得到的数据
char *tmpfile; //临时文件名

timeout.tv_sec = 1; //设置几秒钟超时
timeout.tv_usec = 500000; //设置几微秒超时
web_domain.port=80; //默认端口 为 80

tmpfile="abc.txt";
//******************* 处理命令行的参数 *************************

if(argc<2) //参数不足
{ printf("%s","/n/nExp: ./client http://192.168.1.254:80 /n/n");
exit(1);
}
if(!(tempStr=strstr(argv[1],"http://"))) //必须以 http://开头
{ printf("parameter error!/n");
exit(0);
}
strcpy(web_domain.url,tempStr); //http://www.xh88.com:80/index.php
strcpy(web_domain.host,web_domain.url+7); //www.xh88.com
//处理 host
if((tempStr=strstr(web_domain.host,"/")))
{ *tempStr='/0'; //web_domain.host 里去除:后的东西
}
if((tempStr=strstr(web_domain.host,":")))
{ *tempStr='/0'; //Host 里去除:后的东西
web_domain.port=atoi(tempStr+1); //改写端口
}
//!
printf("%s/n%d/n%s/n",web_domain.host,web_domain.port,web_domain.url);

hostbyname = gethostbyname(web_domain.host); //将基本名字和地址转换
if((sock_id=socket(PF_INET,SOCK_STREAM,0))==-1)
{ perror("socket");
exit(1);
}

//初始化远端要传递的socket
remote_addr.sin_family=AF_INET; //地址族
remote_addr.sin_port=htons(web_domain.port); //端口号
remote_addr.sin_addr=*((struct in_addr *)hostbyname->h_addr); //IP地址
bzero(&(remote_addr.sin_zero),8); //填充0 以保持与struct sockaddr同样大小

//和服务器建立连接
if(connect(sock_id,(struct sockaddr *)&remote_addr,sizeof(remote_addr))==-1)
{ perror("connect");
exit(1);
}
printf("/n/nconnected %s:%d ok!/n/n",web_domain.url,web_domain.port);

//创建要发送给远端的字串
sprintf(send_str,"GET %s HTTP/1.1/nAccept: */*/nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)/nHost: %s/n/n",web_domain.url,web_domain.host);
printf("%s/n/n",send_str);
//开始向服务器发送数据
if(send(sock_id,send_str,strlen(send_str),0)==-1)
{ perror("send");
exit(1);
}
recBuf=malloc(MaxRecvLen); //为储存远端返回的字串的变量申请空间
//fp=fopen(tmpfile,"w");
while(1)
{

//设置无堵塞模式
FD_ZERO(&sockid_readable);
FD_SET(sock_id,&sockid_readable);
select(sock_id+1, &sockid_readable, NULL, NULL, &timeout);
if (!FD_ISSET(sock_id, &sockid_readable))
{ printf("Timed out./n");
break;
}
recv_numb = recv(sock_id,recBuf,MaxRecvLen,0); //得到远端返回的字串
recBuf[recv_numb]='/0';

//fputs(fp,);
// fp=fopen(tmpfile,"w");
printf("/n/t********* %d *******",recv_numb);
printf("%s",recBuf);
if(recv_numb<1) //返回的长度不够退出循环
break;
}

printf("/n/nrecv ok!/n/n");
close(sock_id);
return 0;
}

 

 

 

 

 

 

 

int hex_c2d(char c)  
{
  if(c >;= 'a' && c <= 'f')
    return c-'a'+10;
  else if(c >;= '0' && c <= '9')
    return c-'0';
  else
    return -1;
}
main(int argc,char **argv)  // 16进制数由命令行参数提供
{
char *hex_str;
char *p;
char dec_str[10];     //存放转化的10进制数
int i;
int sum;
int w;
hex_str=argv[1];
p=hex_str+strlen(hex_str)-1;
for(w=1,sum=0;p >;= hex_str;p--) {
sum=sum + w * hex_c2d(*p);
w=w*16;
}
sprintf(dec_str,"%d",sum);
printf(dec_str);
}

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值