客户端与服务器简述


一、基础

计算机是一栋大楼,里面有很多房间,这些房间是程序或者服务。端口是房间的门牌号,比如 80 号房和443 号房。数据像快递包裹,通过门牌号被准确送到对应的房间,即通过端口被送给对应的程序。
这里有一些需要注意的地方。首先,门牌号不能重复,一栋楼里不能有两个 80 号房间;其次,常用的门牌号有固定的用途,比如80号房间专门收“网页快递”,22号房间收“远程控制快递”;最后,有些门牌号需要特权,比如1024以下的端口,如80、443,需要管理员权限sudo才能使用,就像VIP房间,而1024以上的端口,如3000和8000等,普通用户就可以直接使用。

二、代码

1.客户端程序

client.cc代码如下:

extern "C" {
    #include "unp.h"
}


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>");
    }
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        err_sys("socket error");
    }
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(1013);
    if (inet_pton(AF_INET, argv[1], &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;
        if (fputs(recvline, stdout) == EOF) {
            err_sys("fputs error");
        }
    }
    if (n < 0) {
        err_sys("read error");
    }
    exit(0);
}

2.服务器程序

web.cc代码如下:

extern "C" {
    #include "unp.h"
}
#include <time.h>

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

    listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(1013);
    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);
    }
}

客户端与服务器程序形成一对“一问一答”的关系。服务端程序像接电话的服务台,一直等待别人打进来,客户端程序像打电话的人,会主动拨号联系服务端。服务端代码的步骤为

socket()->bind()->listen()->accept()->write()->close()

客户端代码的步骤为

socket()->connect()->read()->close()

服务端程序通过bind(listenfd,...)绑定到1013号端口,用listen()accept()循环等待客户端连接,连接后通过write()发送时间给客户端。客户端程序通过connect(sockfd,...)连接到服务端1013号端口,用read()读取服务端程序返回的数据,并打印到屏幕。
服务端运行在本机(IP为127.0.0.1)的1013号端口,客户端与其交互过程如下:

sudo ./web  #启动服务端
./client 127.0.0.1  #启动客户端

在这里插入图片描述在这里插入图片描述
综上,服务端守株待兔,绑定固定端口,等待连接并响应数据。客户端主动出击,通过IP和端口找到服务端,获取数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值