remote uptime 服务器程序

客户端代码如下

#include<netdb.h>

#include<errno.h>

#include<sys/socket.h>

#include "apue.h"

#define BUFLEN  128

extern int connet_retry(int,int,int, const struct sockaddr *,socklen_t);

//这个函数就是之前提到的重新连接函数,第一参数domain 第二参数是type,第三个参数是protocol

//这三个参数来重定义 套接字 而后面的地址结构,地址长度用在connect 函数上!

void print_uptime(int sock)//整个函数的意思是从这个sock套接字接收字符并打印到屏幕上!

{  int n;

    char buf[BUFLEN];

    while( (n=recv(sockfd,buf,BUFLEN,0))>0 )//这里n是接收多少字符意思,每次调用recv接收到0以上字符时就循环!

   {    write(STDOUT_FILENO,buf,n);

         if( n<0 )err_sys(“recv error”);

    }

}

int main(){

  struct addrinfo *ailist,*aip;//这是地址结构链表的意思

  struct addrinfo hint;//地址结构筛选模板

  int      sockfd,err

 if(argc!=2)err_quit("usage:uptime hostname");

 memset(&hint,0,sizeof(hint));//意思是将hint 全部置0先,模板都是先这样的。

 hint.ai_socktype=SOCK_STREAM; hint.ai_canonname=NULL; hint.ai_addr=NULL;

 hint.ai_next=NULL; 

 if(err=getaddrinfo(argv[1],"ruptime",&hint,&ailist) !=  0 )//这个函数将主机名和服务名一起映射出一个地址链表

     err_quit("getaddrinfo error: %s",gai_strerror(err));

  

for(aip=ailist;aip!=NULL;aip=aip->next){ //然后对地址链表的一个一个地址连接

   if(sock=connect_retry(aip->family,SOCK_STREAM,0,aip->ai_addr,aip->addrlen) < 0 )//sock要是返回失败

    {err=errno;}else{

    print_uptime(sockfd);

    exit(0);

     }//else

    

  }//地址链表循环完成

  err_exit(err,"can't connect to %s",argv[1]);

//ps 很可惜是用hostname 和 getaddrinfo函数来获取地址结构的。这样就无法连接远程的服务器。因为远程服务器的地址结构不知道

//在哪输入给客户端。如果希望改一下,就用inet_pton()函数将字符串地址转换成网络二进制形式绑定给sockaddr地址结构

//并去掉地址结构链表循环,连接 绑定好的 sockaddr即可。地址字符串通过 argv[1] 输入!

服务端代码如下:

#include"apue.h"

#include<netdb.h>

#include<errno.h>

#include<syslog.h>

#include<sys/socket.h>

#define BUFLEN 128

#define QLEN 10

#ifndef HOST_NAME_MAX

#define HOST_NAME_MAX

#endif

 extern int initserver(int,const struct sockaddr *,socklen_t,int);//第一参数就是套接字

//然后后面的参数就是初始化套接字,并且把服务器地址绑定上去。

void serve(int sockfd){

   int clfd; FILE *fp; char buf[BUFLEN];

    set_cloexec(sockfd);//这个函数不清楚

   for(;;){

      if((clfd=accept(sockfd,NULL,NULL)  <0 ){//对任何向sockfd 请求连接的套接字 赋值给clfd。

      {    syslog(LOG_ERR,"ruptimed:accept error:%s".strerror(errno));

            exit(1);

      }//所以整个if结构是处理请求连接的套接字

      set_cloexec(clfd);

      if( (fd=popen("usr/bin/uptime","r")) == NULL){

           snprintf(buf,"error: %s ",strerror(errno) );//将错误信息赋给buf

           send(clfd,buf,strlen(buf),0);//并且把错误信息发送给来连接的套接字

       }//整个if结构处理IO打开读取uptime文件

       else{

            while(fgets(buf,BUFLEN,fp) != NULL )//不断循环重fp文件描述符读取字符进入buf,每次读取BUFLEN长度

                  send(clfd,buf,strlen(buf),0);

                  pclose(fp)l

          }//else

           close(clfd);

 }//for

}//serve

int main(){

     struct addrinfo *ailist,*aip;

     struct addrinfo  hint;

     int sockfd,err,n;

     char    *host;

     if(argc != 1){ err_quit("usage: ruptimed "); }//如果有多余的参数

      if(  (n=sysconf(_SC_HOST_NAME_MAX)) <0 ){ n=HOST_NAME_MAX;}//把主机名的最大值赋给n

      if( (host = malloc(n)) == NULL ){   err_sys("malloc error");     }//给host分配空间

      if(  gethostname(host,n) < 0 )err_sys("gethostname error");//把主机名赋值给host

      daemonize("ruptimed");

      memset(&hint,0,sizeof(hint) );//把模板hint清零

      hint.ai_flags=AI_CANONNAME;//给模板hint 赋值

      hint.ai_socktype=SOCK_STREAM;

      hint.ai_canonname=NULL;

      hint.ai_addr=NULL;

      hint.ai_next=NULL;//hint 赋值完毕

      if( (err=getaddrinfo(host,“ruptime”,&hint,*ailist)) != 0 ){

           syslog(LOG_ERR,"ruptimed: getaddrinfo error :%s", gai_strerror(err) );

           exit(1);}//获取 (本主机-ruptime服务) addrinfo失败后 显示错误信息

       for(aip=ailist;aip != NULL ;aip=aip->next){

                   if( (sockfd=initserver(SOCK_STREAM,aip->ai_addr,aip->ai_addrlen,QLEN)) >= 0){

                       //初始化一个套接字并且让它绑定到本主机的地址上

                       serve(sockfd);//这个函数就是往听取sockfd 并且往试图连接sockfd 的clfd 写数据

                       exit(0);

                   }//if

                        

        }//for      

        exit(1);

}

  

  只可惜只能在本地运行!

  需要改造一下才能变成真正的远程服务器。并且还可以改造成多线程,无连接的远程ruptime服务器。

           

原文地址:https://www.cnblogs.com/zzzPark/p/6423387.html