一个简单的时间获取程序

客户程序:

#include "unp.h"
#include "myerror.h"
int main(int argc,char **argv)
{
  //如果程序参数格式不正确
  if (argc != 2)
    {
      err_quit("usage: a.out <IPaddress>");
    }

  //创建一个TCP套接字,返回sockfd作为套接字描述符
  int sockfd;
  if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
    {
      err_sys("socket error");
    }

  /*
  指定服务器的IP地址与端口
  */
  struct sockaddr_in servaddr;
  bzero(&servaddr,sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(9999);//解释见服务器程序
  //inet_pton("呈现形式到数值"),把ASCII命令行参数转换为合适的格式
  //argv[1]代表服务器IP地址
  if (inet_pton(AF_INET,argv[1],&servaddr.sin_addr) < 0)
    {
      err_quit("inet_pton err for %s",argv[1]);
    }

  /*
  建立与服务器的连接
  connect函数应用于一个TCP套接字时,将与由他的第二个参数只想的套接字地址结构
  指定的服务器建立一个TCP连接。
  在unp.h头文件中,将SA定义为struct sockaddr。
  */
  if (connect(sockfd,(SA *)&servaddr,sizeof(servaddr)) < 0)
    {
      err_sys("connect error");
    }

  /*
  读入并输出服务器的应答:
  **使用TCP时必须小心,因为TCP是一个没有记录边界的字节流协议
  */
  int n;
  char recvline[MAXLINE + 1];
  //如果数据量很大,我们不能保证一次read就可一返回服务器的所有应答。
  //当read返回0(对端关闭连接)或者负值(发生错误)时,终止循环。
  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终止程序运行,UNIX在一个进程终止时总是关闭该进程所有打开的
  描述符,我们的TCP套接字就此关闭!
  */
  exit(0);
}


服务器程序:

#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;

  /*
  创建一个网际(AF_INET)字节流(SOCK_STREAM)套接字,
  并以listenfd返回其描述符。
  */
  listenfd = socket(AF_INET,SOCK_STREAM,0);

  /*
  通过填写一个网际套接字地址结构并调用bind函数,将服务器的一个端口
  绑定到所创建的套接字上。
  */
  bzero(&servaddr,sizeof(servaddr));//bzero将整个结构体清零
  servaddr.sin_family = AF_INET;//将地址族设置为AF_INET
  /*
  INADDR_ANY:指定IP地址为INADDR_ANY,这样要是服务器主机
  有多个网络接口,服务器进程就可一在任意网路接口上接受连接。
  */
  servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
  /*
  将服务器开放的端口设定为9999,原文中设定的是13,
  如果按照原文的示例,则该程序运行时需要获取root权限,才能申请使用13号端口
  但是在将服务器开放端口设为9999之后,需要在客户端程序的访问端口处,
  改为9999,不然会出现访问受限的情况!
  网际套接字地址结构中IP地址和端口号这两个成员必须使用特定格式,
  为此我们使用htons("主机到网络短整数")去转换二进制端口号。
  */
  servaddr.sin_port = htons(9999);

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

  /*
  调用listen函数将该套接字转换成一个监听套接字,
  这样来自客户的外来连接就可以在该套接字上有内核接受
  */
  //LISTENQ指定系统内核允许在这个监听描述符上排队的最大客户连接数
  listen(listenfd,LISTENQ);

  /*
  接受客户连接,发送应答
  */
  for(;;)
    {
      /*
    TCP的三路握手,进行连接。
    完成TCP连接之后,accept函数返回一个“已连接描述符”
    该描述符用于与新近连接的那个客户端进行通信。
    accept为每个连接到本服务器的客户返回一个新的描述符。
      */
      connfd = accept(listenfd,(struct sockaddr *)NULL,NULL);

      //获取当前系统时间
      ticks = time(NULL);
      //ctime将整数值转换成直观可读的时间格式
      snprintf(buff,sizeof(buff),"%.24s\r\n",ctime(&ticks));
      //write函数将把结果字符串写给客户
      write(connfd,buff,strlen(buff));

      //终止连接,TCP的四次挥手
      close(connfd);
    }

  exit(0);
}

测试:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值