基於TCP的C/S初級網路編程2

來源:互聯網
上載者:User
導讀

本篇文章對http://www.daoluan.net/?p=774中的“計算機”進行改進,與大家分享。

上面那篇中的服務端屬重複型,即一個時刻只處理一客戶的請求,處理期間不搭理其他客戶。此篇對上篇的“計算機”進行小小的改進——能夠接受多個客戶的請求。

改進細則:

  1. 獨立bind,listen,accept,serve(即calc過程)功能模組;
  2. 所有錯誤成功提示提取至各功能模組(函數)之外,錯誤/成功根據各函數的傳回值判斷(這更符合UNIX編程風範);
  3. 客戶的服務過程由產生的子進程負責。

缺陷:由子進程來負責serve的部分。伺服器主進程(父進程)不負責等待子進程結束,資源由核心回收(這一要非必要)。

上實驗結果圖片解解饞

伺服器啟動

用戶端方面,將client1、client2和client3(編譯連結自同一個代碼)寫進指令碼。運行

服務端服務多個客戶請求

client

#include <stdio.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h>#include <arpa/inet.h>#include <string.h>#include <string.h>#define MAXSLEEP 1024int connect_retry(int sockfd,const struct sockaddr * addr,socklen_t alen){    int nsec;    printf("connecting\n");    for(nsec = 1; nsec <= MAXSLEEP; nsec<<=1)    {        if(connect(sockfd,addr,alen) == 0)        {            printf("connected\n");            return 0;        }// if        if(nsec <= MAXSLEEP/2)//    delay            sleep(nsec);    }// for:    return 0;}int main(int argc,char * argv[]){    if(argc != 4)    {        printf("you must input 4 arg\n");        return 1;    }// if    int fd;        struct sockaddr_in si,server;    char addr[20],buf[20],bufrecv[20];    bzero(bufrecv,sizeof(bufrecv));    sprintf(addr,"127.0.0.1");    fd = socket(AF_INET,SOCK_STREAM,0);//   create socker fd;    printf("socket ok\n");//prepare server addr    bzero(&server,sizeof(server));    server.sin_family = AF_INET;    server.sin_port = htons(6000);    inet_pton(AF_INET,addr,(void *)&server.sin_addr);    printf("server ok\n");//prepare request data    bzero(buf,sizeof(buf));    sprintf(buf,"%c%c%c",argv[1][0],argv[2][0],argv[3][0]);//connect    if(connect_retry(fd,(struct sockaddr *)&server,sizeof(server)) < 0)    {        printf("connect error\n");        return 1;    }// if//send    if(send(fd,buf,20,0) < 0)     {        printf("client send error\n");        return 1;    }// if//select    fd_set readfd;    FD_ZERO(&readfd);    FD_SET(fd,&readfd);    int t;    if((t = select(FD_SETSIZE,&readfd,NULL,NULL,NULL)) < 0)    {        printf("select error\n");        return 1;    }// if//recv    bzero(bufrecv,sizeof(bufrecv));    recv(fd,bufrecv,20,0);    printf("%s\n",bufrecv);    close(fd);    return 0;}

server

#include <stdio.h>#include <sys/socket.h>#include <netinet/in.h>#include <errno.h>#include <ctype.h>#include <arpa/inet.h>#include <unistd.h>#include <string.h>char bufret[20];int initserver(int type,const struct sockaddr * addr,socklen_t alen,int qlen){    int fd;    int err = 0;    if((fd = socket(addr->sa_family,type,0)) < 0)        return -1;    printf("binding\n");    if(bind(fd,addr,alen) < 0)    {        err = errno;        goto errout;    }// if    printf("bind succeed \n");    if(type == SOCK_STREAM || type == SOCK_SEQPACKET)    {        printf("listening\n");        if(listen(fd,1) < 0)        {            err = errno;            printf("listen error\n");            goto errout;        }// if    }// if    printf("listened \n");    return (fd);errout:    close(fd);    errno = err;    return -1;}int serve(int sockfd){    int a,b;    char op,buf[25];    int ret,addrlen = sizeof(struct sockaddr_in),clfd;     struct sockaddr_in client;    bzero(&client,sizeof(client));//accept       printf("accepting\n");    clfd = accept(sockfd,(struct sockaddr *)&client,&addrlen);//recv    printf("accepted\n");    bzero(buf,sizeof(buf));    recv(clfd,buf,20,0);    printf("recived\n");//calculate    a = buf[0] - '0';    b = buf[1] - '0';    op = buf[2];    switch(op)    {        case '+':ret = a + b;break;        case '-':ret = a - b;break;        case '*':ret = a * b;break;        case '/':ret = a / b;break;    }// switch    sprintf(bufret,"the result:%d",ret);//send    printf("sending\n");    if(send(clfd,bufret,20,0) < 0)    {        printf("server send error\n");        return -1;    }// if    printf("sended,server end\n");    return 0;}int main(int argc,char * argv[]){    int sockfd;    char addr[20];    bzero(addr,sizeof(addr));    sprintf(addr,"127.0.0.1");    struct sockaddr_in server;    bzero(&server,sizeof(server));    server.sin_family = AF_INET;    server.sin_port = htons(6000);    //server.sin_addr.s_addr = htonl(INADDR_ANY);    inet_pton(AF_INET,addr,(void *)&server.sin_addr);//prepare server    if((sockfd = initserver(SOCK_STREAM,(struct sockaddr *)&server,sizeof(server),1)) < 0)    {        printf("initserver error\n");        return 0;    }// if    printf("serving\n");//serve    serve(sockfd);    close(sockfd);    return 0;}

test.sh

#!/bin/bash./client1 1 2 +./client2 2 3 +./client3 3 4 +

本文完 2012-08-06

搗亂小子 http://www.daoluan.net/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.