网络编程第一篇:客户--服务器通信(非阻塞,多进程)

 
来源: ChinaUnix博客  日期: 2008.08.31 15:20 (共有条评论) 我要评论
 

                /* common_talk.h */
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXMSG 1024
#define MSG_FD_NUM 2
#define MSG_FD_STDIN 0
#define MSG_FD_SOCK 1
char msgbuf[MAXMSG+2];    // \r \0
void do_talk(int new_fd)
{
    fd_set rfds;
    struct timeval tv;
    int maxfd;
    int fdsets[MSG_FD_NUM];
    fdsets[MSG_FD_STDIN] = STDIN_FILENO;
    fdsets[MSG_FD_SOCK] = new_fd;
    int len,i;
    
    printf("input the message you want,then press Enter(\"quit\"---end this talk)\n");
    while(1){        
        FD_ZERO(&rfds);
        FD_SET(fdsets[MSG_FD_STDIN],&rfds);  
        FD_SET(fdsets[MSG_FD_SOCK],&rfds);      //检测标准输入和通话套接字        
        tv.tv_sec = 1;
        tv.tv_usec = 0;   //等待一秒;
        maxfd = fdsets[MSG_FD_STDIN] > fdsets[MSG_FD_SOCK] ? fdsets[MSG_FD_STDIN]:fdsets[MSG_FD_SOCK];
        if(select(maxfd+1,&rfds,NULL,NULL,&tv)>%s",msgbuf);                      
                          printf("\t\tsend message sucess ---- totally send %d bytes message\n",len);
                          break;
                        
                    case MSG_FD_SOCK:
                          memset(msgbuf,0x00,sizeof(msgbuf));
                          if((len=recv(new_fd,msgbuf,MAXMSG,0))>0){
                              printf("server received>> %s \n",msgbuf);                      
                              printf("\t\treceived message success ----totally received %d bytes messages\n",len);                
  
                          }else{
                                if(len ==0)
                                      printf("client exited\n");
                                  else
                                      printf("receive error,errno=%d error information:%s",errno,strerror(errno));    
                                  return ;                                
                          }
                          break;
                }        
            }
        }//for
    }//while
}
void sig_chld(int signum)
{
    pid_t pid;
    int status;
    
    printf("recived SIGCHLD,child process exited,");    
    while((pid = waitpid(-1,&status,WNOHANG))>0){
             printf("pid =%d\n",pid);
        }
    return;    
}
/* server.c*/
#include"common_talk.h"
void usage(void)
{
    fprintf(stderr,"\nmyserver usage:\n");
    fprintf(stderr,"./myserver -p  -b  [-h]\n");
    fprintf(stderr,"   -p   server's port\n");\
    fprintf(stderr,"   -b   queue number of  pending  connections\n");
    fprintf(stderr,"   -h   how to use\n");
    return;
}
void getmyopt(int *port, int *backlog,int argc, char *argv[])
{
    char ch;    
    *port =0;
    *backlog =0;
       
    while( (ch=getopt(argc,argv,":p:b:h")) != -1 ){
        switch(ch){
            case 'p': 
                *port = atoi(optarg);
                break;
            case 'b':   
                *backlog = atoi(optarg);
                break;
            case 'h':   
                usage();
                break;
            case ':':   
                printf("%s:option -%c requires an argument\n",argv[0],optopt);
                exit(1);
            case '?':
                printf("%s:option -%c is an invalid argument\n",argv[0],optopt);
                exit(1);               
        }
    }
    if(*port ==0 || *backlog==0){
        printf("option -p and -b must be given\n");
        usage();
        exit(1);
    }
}
int main(int argc, char *argv[])
{
    struct sockaddr_in srvaddr,cliaddr;
    int sock_fd,new_fd;
    int opt = 1,len;
    int sin_size;
    pid_t pid;
    char hostname[20];
    int status;
    int n,ret;
    int srvport,backlog;
    
    getmyopt(&srvport,&backlog,argc,argv);
    
    sock_fd = socket(AF_INET, SOCK_STREAM,0);
    if(sock_fd==-1){
        perror("socket\n");
        exit(1);    
    }
    memset(&srvaddr,0x00,sizeof(srvaddr));
    memset(&cliaddr,0x00,sizeof(cliaddr));
    memset(msgbuf,0x00,sizeof(msgbuf));
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_port = htons(srvport);
    srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        
    len = sizeof(opt);
    if(setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&opt,len)  -a  [-h]\n");
    fprintf(stderr,"   -p   server's port\n");\
    fprintf(stderr,"   -a   server's address\n");
    fprintf(stderr,"   -h   how to use\n");
    return;
}
    
void getmyopt(int *port, char *ip,int argc, char *argv[])
{
    char ch;    
    *port =0;
    
    while( (ch=getopt(argc,argv,":p:a:h")) != -1 ){
        switch(ch){
            case 'p': 
                *port = atoi(optarg);
                break;
            case 'a':   
                printf("optarg=%s\n",optarg);
                sprintf(ip,"%s",optarg);
                break;
            case 'h':   
                usage();
                break;
            case ':':   
                printf("%s:option -%c requires an argument\n",argv[0],optopt);
                exit(1);
            case '?':
                printf("%s:option -%c is an invalid argument\n",argv[0],optopt);
                exit(1);               
        }
    }
    if(*port ==0 || *ip==0){
        printf("option -p and -a must be given\n");
        usage();
        exit(1);
    }
}
    
int main(int argc, char *argv[]){
    struct sockaddr_in srvaddr;
    int sockfd,new_fd;
    int opt = 1,len;
    int sin_size;
    char ip[20];
    int srvport;
    int n;
    
    memset(ip,0x00,20);
    memset(&srvaddr,0x00,sizeof(srvaddr));
    
    sockfd = socket(AF_INET, SOCK_STREAM,0);
    if(sockfd==-1){
        perror("socket\n");
        exit(1);    
    }
    getmyopt(&srvport,ip,argc,argv);   
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_port = htons(srvport);
    srvaddr.sin_addr.s_addr = inet_addr(ip);
    sockfd = socket(AF_INET, SOCK_STREAM,0);
    if(sockfd==-1){
        perror("socket\n");
        exit(1);    
    }
    
    len = sizeof(opt);
    if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,len) < 0){
        perror("setsockopt");
        exit(1);    
    }
    printf("client socket initilize success\n");
            
    if(connect(sockfd,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr)) < 0){
        printf("connect:%s",strerror(errno));
        close(sockfd);
        exit(1);    
    }
    printf("connect to a server success\n");
    do_talk(sockfd);
    close(sockfd);
}
主要知识点: 
1.在命令行方式下的参数处理,使用getopt()函数可以处理短参数方式,如果参数后跟一个参数值,则optarg指向这个参数值,如果为无效参数,getopt返回“:”,如果需要跟一个参数值而没有跟,则返回“?”
可以使用getopt_long处理长参数方式。
2.网络中处理客户端通常采用多进程方式,采用select轮询,不过现在为支持大吞吐量好像使用epoll很好。
3.信号量的捕捉,通常是不建议在信号函数中使用printf等不可重入函数,例子只是为了演示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值