第11章 连接到近端或远端的进程:服务器与Socket(套接字)

本文介绍了一个简单的基于socket的时间服务器实现及其客户端。服务器通过监听指定端口接收客户端连接请求,并返回当前时间;客户端则向服务器发起请求并显示接收到的时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
 * timeserv.c   a socket - based time of day server
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <strings.h>

#define PORTNUM     13000       /* our time service phone number */
#define HOSTLEN     256
#define oops(msg)       { perror(msg);  exit(1); }

int main(int ac, char *av[])
{
    struct  sockaddr_in saddr;                              /* build our address here */
    struct  hostent     *hp;                                /* this is part of our */
    char    hostname[HOSTLEN];                              /* address */
    int     sock_id, sock_fd;                               /* line id, file desc */
    FILE    *sock_fp;                                       /* use socket as stream */
    char    *ctime();                                       /* convert secs to string */
    time_t  thetime;                                        /* the time we report */

    /* 
     * Step 1: ask kernel for a socket
     */
    sock_id = socket(PF_INET, SOCK_STREAM, 0);              /* get a socket */
    if (sock_id == -1)
        oops("socket");

    /*
     * Step 2: bind address to socket. Address is host, port;
     */
    bzero((void *)&saddr, sizeof(saddr));                   /* clear out struct */

    gethostname(hostname, HOSTLEN);                         /* where am I? */
    hp = gethostbyname(hostname);                           /* get info ahout host */
                                                            /* fill in host part */

    bcopy((void *)hp->h_addr, (void *)&saddr.sin_addr,
            hp->h_length);
    saddr.sin_port = htons(PORTNUM);                        /* fill in socket port */
    saddr.sin_family = AF_INET;                             /* fill in addr family */

    if (bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0)
        oops("bind");

    /*
     * Step 3: allow incoming calls with Qsize = 1 on socket
     */
    if (listen(sock_id, 1) != 0)
        oops("listen");

    /*
     * main loop: accept(), write(), close()
     */
    while (1) {
        sock_fd = accept(sock_id, NULL, NULL);              /* wait for call */
        printf("Wow,! got a call!\n");
        if (sock_fd == -1)
            oops("accept");                                 /* error getting calls */

        sock_fp = fdopen(sock_fd, "w");                     /* we'll write to the */
        if (sock_fp == NULL)                                /* socket as a stream */
            oops("fdopen");                                 /* unless we can't */

        thetime = time(NULL);                               /* get time */
                                                            /* and convert to string */
        fprintf(sock_fp, "The time here is..");
        fprintf(sock_fp, "%s", ctime(&thetime));
        fclose(sock_fp);                                    /* release connection */
    }
}
/*
 * timeclnt.c - a client for timeserv.c
 *          usage: timeclnt hostname portnumber
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define oops(msg)           { perror(msg); exit(1); }

main(int ac, char *av[])
{
    struct  sockaddr_in servadd;            /* the number to call */
    struct  hostent     *hp;                /* used to get number */
    int     sock_id, sock_fd;               /* the socket and fd */
    char    message[BUFSIZ];                /* to receive message */
    int     messlen;                        /* for message length */

    /*
     * Step 1: Get a socket
     */
    sock_id = socket(AF_INET, SOCK_STREAM, 0);              /* get a line */
    if (sock_id == -1)
        oops("socket");                                     /* or fail */

    /*
     * Step 2: connect to server
     *      need to build address(host, port) of server first
     */
    bzero(&servadd, sizeof(servadd));       /* zero the address */

    hp = gethostname(av[1]);                /* lookup hosts ip # */
    if (hp == NULL)
        oops(av[1]);                        /* or die */

    bcopy(hp->h_addr, (struct sockaddr *)&servadd.sin_addr,
            hp->h_length);

    servadd.sin_port = htons(atoi(av[2]));  /* fill in port number */
    servadd.sin_family = AF_INET;           /* fill in socket type */
                                            /* now dial */
    if (connect(sock_id, (struct sockaddr *)&servadd,
                sizeof(servadd)) != 0)
        oops("connect");

    /*
     * Step 3: transfer data from server, then hangup
     */
    messlen = read(sock_id, message, BUFSIZ);           /* read stuff */
    if (messlen == -1)
        oops("read");
    if (write(1, message, messlen) != messlen)          /* and write to */
        oops("write");                                  /* stdout */
    close(sock_id);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值