簡單的時間/日期客戶端&服務器程序

簡單的時間/日期客戶端&服務器程序

本文章代碼根據《UNIX網絡編程:卷1》修改而來,由於書中源碼用於linux系統,題主在windows系統下進行模擬操作,作了部分修改。


客戶端程序

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fcntl.h>
#include <Windows.h>
#include <winsock.h>
#include <winsock2.h>
#include "my_err.h"

#define bzero(ptr,n)    memset(ptr,0,n)
#define SA  struct sockaddr

void     err_quit(const char *, ...);
void     err_sys(const char *, ...);

int main(int argc,char **argv)
{
    int                 sockfd,n;
    char                recvline[MAXLINE + 1];
    struct sockaddr_in  servaddr;

    if(argc != 2)
        err_quit("usage: a.out <IPaddress>");
    WSADATA wsa;
    WORD wVersionRequested;
    wVersionRequested = MAKEWORD(2,0);
    if(WSAStartup(wVersionRequested,&wsa)!=0){
        printf("Winsock Initialization failed.\n");
    }
    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
        err_sys("socket error");
    std::cout<<sockfd<<std::endl;

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(13);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    /*
    *   int inet_pton(int af,const char *sr,void *dst);
    *   af:     地址簇
    *   *sr:    來源地址
    *   *dst:   接收轉換後的數據
    */
    // if(inet_ntop(AF_INET ,argv[1],&servaddr.sin_addr,sizeof(servaddr.sin_addr)) <= 0)
    //  err_quit("inet_pton error for %s",argv[1]);

    if(connect(sockfd,(SA *) &servaddr,sizeof(servaddr)) < 0)
        err_sys("connect error");

    while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
        recvline[n] = 0;    /* null terminate */
        if (fputs(recvline, stdout)r_sys("fputs error");
    }
    if (n < 0)

        err_sys("read error");

    exit(0);
}

服務器程序

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fcntl.h>
#include <Windows.h>
#include <winsock.h>
#include <winsock2.h>
#include "my_err.h"

#define bzero(ptr,n)    memset(ptr,0,n)
#define SA  struct sockaddr
#define LISTENQ     1024    /* 2nd argument to listen() */

int main(int argc,char **argv)
{
    int         listenfd,connfd;
    struct sockaddr_in servaddr;
    char        buff[MAXLINE];
    time_t      ticks;

    WSADATA wsa;
    WORD wVersionRequested;
    wVersionRequested = MAKEWORD(2,0);
    if(WSAStartup(wVersionRequested,&wsa)!=0){
        printf("Winsock Initialization failed.\n");
    }

    listenfd = socket(AF_INET,SOCK_STREAM,0);
    std::cout<<listenfd<<std::endl;

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(13);   /* daytime server */

    bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

    listen(listenfd, LISTENQ);

    for ( ; ; ) {
        connfd = accept(listenfd, (SA *) NULL, NULL);

        ticks = time(NULL);
        snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
        write(connfd, buff, strlen(buff));

        //close(connfd);
    }
}

my_err.h 代碼塊如下:

#include <errno.h>      /* for definition of errno */
#include <stdarg.h>     /* ISO C variable aruments */

#define MAXLINE 4096

static void err_doit(int, int, const char *, va_list);

 /*
  * Nonfatal error related to a system call.
  * Print a message and return.
  */
void
err_ret(const char *fmt, ...)
 {
     va_list     ap;

     va_start(ap, fmt);
     err_doit(1, errno, fmt, ap);
     va_end(ap);
 }


 /*
  * Fatal error related to a system call.
  * Print a message and terminate.
  */
void
 err_sys(const char *fmt, ...)
 {
     va_list     ap;

     va_start(ap, fmt);
     err_doit(1, errno, fmt, ap);
     va_end(ap);
     exit(1);
 }


 /*
  * Fatal error unrelated to a system call.
  * Error code passed as explict parameter.
  * Print a message and terminate.
  */
 void
 err_exit(int error, const char *fmt, ...)
 {
     va_list     ap;

     va_start(ap, fmt);
     err_doit(1, error, fmt, ap);
     va_end(ap);
     exit(1);
 }


 /*
  * Fatal error related to a system call.
  * Print a message, dump core, and terminate.
  */
 void
 err_dump(const char *fmt, ...)
 {
     va_list     ap;

     va_start(ap, fmt);
     err_doit(1, errno, fmt, ap);
     va_end(ap);
     abort();        /* dump core and terminate */
     exit(1);        /* shouldn't get here */
 }


 /*
  * Nonfatal error unrelated to a system call.
  * Print a message and return.
  */
 void
 err_msg(const char *fmt, ...)
 {
     va_list     ap;

     va_start(ap, fmt);
     err_doit(0, 0, fmt, ap);
     va_end(ap);
 }


 /*
  * Fatal error unrelated to a system call.
  * Print a message and terminate.
  */
 void
 err_quit(const char *fmt, ...)
 {
     va_list     ap;

     va_start(ap, fmt);
     err_doit(0, 0, fmt, ap);
     va_end(ap);
     exit(1);
 }


 /*
  * Print a message and return to caller.
  * Caller specifies "errnoflag".
  */
static void
err_doit(int errnoflag, int error, const char *fmt, va_list ap)
{
    char    buf[MAXLINE];
    vsnprintf(buf, MAXLINE, fmt, ap);
    if (errnoflag)
        snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s",
          strerror(error));
    strcat(buf, "\n");
    fflush(stdout);     /* in case stdout and stderr are the same */
    fputs(buf, stderr);
    fflush(NULL);       /* flushes all stdio output streams */
}

運行測試時,先運行服務器代碼,再運行客戶端代碼,服務器會一直處於偵聽狀態,客戶端連接127.0.0.1,connect成功,但是會read error,提示Bad file descriptor。

但是,把服務器和客戶端中write()和read()函數相應地改成send()和recv()就可以成功進行接收數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章