基于Linux平台实现的流式套接字客户端服务器端代码

(1)服务器段代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <time.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define BUFSIZE 512
/*
 * 错误报告
 */
static void bail(const char *on_what){

    fputs(strerror(errno), stderr);
    fputs(": ", stderr);
    fputs(on_what, stderr);
    fputc('\n', stderr);  
    exit(1);
}

int main(int argc, char *argv[]){   
   int sockfd;                  /* 服务器套接字 */
    int new_fd;                  /* 服务器连接套接字 */
    struct sockaddr_in server_addr;  /* 服务器监听套接字 */
    struct sockaddr_in client_addr;  /* 客户端IP地址 */
                                    
    socklen_t size;
    int portnumber;

    char reqBuf[BUFSIZE];  	/* 应用接收缓存 */
    char dtfmt[BUFSIZE];   	/* 日期-时间结果字符串 */
    time_t td;       		 	/* 当前日期和时间 */
    struct tm tm;    			/* 日期时间结构体 */
    int z;

    if(argc != 2){
        fprintf(stderr, "Usage: %s portnumber\a\n", argv[0]);
        exit(1);
    }

    if((portnumber = atoi(argv[1]))<0){
        fprintf(stderr, "Usage: %s portnumber\a\n", argv[0]);
        exit(1);
    }


    /* 创建服务器监听套接字 */
    if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1){
        fprintf(stderr, "Socket error: %s\a\n", 
                        strerror(errno));
        exit(1);
    }


    /* 为监听套接字准备IP地址和端口 */
    memset(&server_addr, 0, sizeof server_addr);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    server_addr.sin_port = htons(portnumber);

    /* 绑定套接字到指定地址和端口 */
    if ((bind (sockfd, (struct sockaddr *)(&server_addr),
                        sizeof server_addr)) == -1){
        fprintf(stderr, "Bind error: %s\a\n", strerror(errno));
        exit(1);
    }

    /* 监听 */
    if (listen(sockfd, 128) == -1) {
        fprintf(stderr, "Listen error: %s\n\a", 
                        strerror(errno));
        exit(1);
    }
    printf("waiting for the client's request...\n");
    /* 服务器主循环处理 */
    while (1) {
        size = sizeof (struct sockaddr_in);

        /* 接收一个客户端连接并创建服务器连接套接字 */
        if((new_fd = accept(sockfd, 
                   (struct sockaddr *)(&client_addr), &size)) == -1){
             fprintf(stderr, "Accept error: %s\a\n", 
                            strerror(errno));
             exit(1);
        }

        fprintf(stdout, "Server got connection from %s\n",
            inet_ntoa(client_addr.sin_addr));
        for(;;) {
            /* 读取客户端发来的日期时间请求,若客户端没有发送请求,
             * 则服务器将阻塞  
             */
            z = read (new_fd, reqBuf, sizeof reqBuf);
            if(z < 0)
                bail("read()");
            /* 服务器检查客户端是否关闭了套接字,此时read操作
             * 返回0(EOF )。如果客户端关闭了其套接字,则服务器
            * 将执行close 结束此连接,然后开始接收下一个客户端
             * 的连接请求
            */
            if(z == 0) {
               close (new_fd);
                break;
            }
            /*
             * 向请求连接字符串尾添加NULL字符构成完整的请求日
             * 期时间字符串 
             */

            reqBuf[z] = 0;

            /*
             * 获得服务器当前日期和时间
             */

            time(&td);
           tm = *localtime(&td);

            /*
             * 根据请求日期字符串的格式字串生成应答字符串
             */ 
             strftime(dtfmt,  /* 格式化结果 */
            		sizeof dtfmt,
                	reqBuf,        /* 客户端请求格式字串 */
                	&tm);
				/* 将格式化结果发送给客户端 */

             z = write (new_fd, dtfmt, strlen(dtfmt));
             if(z < 0)
				   bail("write()");
          }   
       }         
   }    

(2)客户端代码:

 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
 #include <netdb.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <unistd.h>
 #include <arpa/inet.h>

 #define BUFSIZE 512

 static void bail(const char *on_what){
    fputs(strerror(errno), stderr);
     fputs(": ", stderr);
     fputs(on_what, stderr);
     fputc('\n', stderr);
    exit(1);

 }


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

    int sockfd;                             /*客户端套接字*/
    char buf[BUFSIZE];
    struct sockaddr_in server_addr;     /* 服务器IP地址*/
    struct hostent *host;
    int portnumber;
    int nbytes;
    int z;
    char reqBuf[BUFSIZE];                 /*客户端请求格式字符串 */
    if (argc != 3) {
        fprintf(stderr, "Usage: %s hostname portnumber\a\n", 
                        argv[0]);
        exit(1);

    }
    if ((host = gethostbyname(argv[1])) == NULL) {

        fprintf(stderr, "Gethostname error\n");
       exit(1);

    }
    if ((portnumber = atoi(argv[2])) < 0) {
      fprintf(stderr, "Usage: %s hostname portnumber\a\n", 
                       argv[0]);
        exit(1);

    }

    /*创建套接字 */

    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {

        fprintf(stderr, "Socket Error: %s\a\n", 

                        strerror(errno));

        exit(1);

    }

    /* 创建服务器地址*/
    memset(&server_addr, 0, sizeof server_addr);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(portnumber);
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    /*链接服务器*/
    if (connect(sockfd, (struct sockaddr *)(&server_addr),
        sizeof server_addr) == -1) {
        fprintf(stderr, "Connect Error: %s\a\n", 
                        strerror(errno));
        exit(1);
    }

    printf("connected to server %s\n", 
                  inet_ntoa(server_addr.sin_addr));

    /*
    *客户端程序主循环,输入‘quit’退出
    */

   for (;;) {

        /* 提示输入日期时间格式字符串 */
        fputs("\nEnter format string(^D or 'quit' to exit): ", 
                      stdout);

        if (!fgets(reqBuf, sizeof reqBuf, stdin)) {
            printf("\n");
            break;      /* EOF */
        }

        /*
        * 为日期时间请求字符串添加NULL字符串作为结尾,另外同时去掉末尾的换行符
        */

       z = strlen(reqBuf);

        if (z > 0 && reqBuf[--z] == '\n')
            reqBuf[z] = 0;
        if (z == 0)  /*客户端进输入了enter */
           continue;
        /*
        * 输入 quit 退出
        */

        if (!strcasecmp(reqBuf, "QUIT")) {
            printf("press any key to end client.\n");
            getchar();
            break;

        }
        /*
        * 发送日期时间请求字符串到服务器,注意请求信息中去掉了NULL字符
        */
       z = write(sockfd, reqBuf, strlen(reqBuf));
        printf("client has sent ??%s?? to the sever\n", reqBuf);
        if (z < 0)
           bail("write()");

        /*
        * 从客户端套接字中读取服务器发回的应答
        */
        if ((nbytes = read(sockfd, buf, sizeof buf)) == -1) {
            fprintf(stderr, "Read Error: %s\n", 
                            strerror(errno));
            exit(1);
        }
        /*
        * 若服务器由于某一种原因关闭了链接,则客户段需要处理此事件
        */
      if (nbytes == 0) {  /* ????EOF */

           printf("server has closed the socket.\n");
           printf("press any key to exit...\n");
            getchar();
            break;
        }

        buf[nbytes] = '\0';

       /*
       * 输出日期时间结果
       */
       printf("result from %s port %u :\n\t'%s'\n",
           inet_ntoa(server_addr.sin_addr),
           (unsigned)ntohs(server_addr.sin_port),
            buf);
   }
   close(sockfd);
   return 0;
}

(3)执行程序

技术分享

技术分享


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。