网络学习小记4

2024.12.16

1、通过主机名和服务名获取目标服务器上的daytime服务

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <arpa/inet.h>

int main(int argc,char *argv[]){
    assert(argc==2);
    char *host = argv[1];
    //获取目标主机地址信息
    struct hostent* hostinfo = gethostbyname(host);
    char ip[128];
    assert(hostinfo);
    printf("host name is %s\n",hostinfo->h_name);
    printf("host ip is %s\n",inet_ntop(AF_INET,hostinfo->h_addr_list,ip,INET_ADDRSTRLEN));
    //获取daytime服务信息
    struct servent* servinfo = getservbyname("daytime", "tcp");
    assert(servinfo);
    printf("daytime port is %d\n",ntohs(servinfo->s_port));

    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_port = servinfo->s_port;
    address.sin_addr = *(struct in_addr*)*hostinfo->h_addr_list;

    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    int result = connect(sockfd,(struct sockaddr*)&address,sizeof(address));
    assert(result!=-1);

    char buffer[128];
    result = read(sockfd,buffer,sizeof(buffer));
    assert(result>0);
    buffer[result] = '\0';
    printf("the day item is %s\n",buffer);
    close(sockfd);

    return 0;
}

注意getservbyname和getservebyport函数实际上都是通过读取(本机的)/etc/services来获取服务信息的。

这里为了方便测试选择了本机hostname,不过运行结果显示的ip有点奇怪:

每次运行结果的host ip除了以192开头外都不一样,可能是返回的随机ip?

2、利用dup函数实现一个基本的CGI服务器

服务器程序:

#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>

int main(int argc,char *argv[]){
    assert(argc==3);
    const char *ip =  argv[1];
    int port = atoi(argv[2]);

    struct sockaddr_in address;
    bzero(&address, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_port = htons(port);
    inet_pton(AF_INET,ip,&address.sin_addr);

    int sock = socket(PF_INET,SOCK_STREAM,0);
    assert(sock>=0);

    int ret = bind(sock,(struct sockaddr*)&address,sizeof(address));
    assert(ret!=-1);

    ret = listen(sock, 5);
    assert(ret!=-1);

    struct sockaddr_in client;
    socklen_t client_addrlength = sizeof(client);
    int connfd = accept(sock, (struct sockaddr*)&client, &client_addrlength);
    if(connfd<0) printf("errno is %d\n",errno);
    else{
        close(STDOUT_FILENO);//标准输出文件描述符STDOUT_FILENO的值是1
        dup(connfd);//dup会返回系统中最小的可用的文件描述符,所以其返回值实际上是1,所以服务器标准输出的内容就会直接发送到与客户连接对应的socket上
        //这就是CGI服务器的基本工作原理
        printf("abcd\n");
        close(connfd);
    }
    close(sock);

    return 0;
}

客户端运行结果:

dup()函数实际上做的是创造一个新的文件描述符,该新文件描述符和原有文件描述符(形参)指向相同的文件,管道或者网络连接,这里实现重定向是利用了其返回系统当前可用的最小整数值的性质,也就是或让值为1的文件描述符重新指向了connfd指向的文件,而printf函数默认会向值为1的文件描述符指向的文件输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值