unix网络基础-TCP时间获取服务器程序

来源:互联网 发布:全国省市县乡镇数据库 编辑:程序博客网 时间:2024/05/13 05:35

TCP时间获取服务器程序

服务器程序实际上和客户端程序差不多,服务器程序需要通过填写一个网络套接字地址结构并调用bind函数,将众所周知的端口(时间获取服务是13)绑定到创建的套接字。
之后我们指定IP地址为INADDR_ANY,这样一个服务器可有多个网络接口,服务器进程可以与任意客户连接。
以下是修改过的代码:
#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(13);    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);    }}

1.sockaddr_in已经在前面讲过,此处不再赘述。

2.MAXLINE是在unp.h中定义的宏。

3.Socket函数是在socket函数的基础上封装的函数,相比socket主要多了错误处理的功能,从而减少了冗余代码。
如下:(仅供参考)
int Socket(int family, int type, int protocol){    int n;       if((n = socket(family, type, protocol)) < 0)    {        printf("socket error");        exit(1);     }     return(n);}

4.bzero函数将servaddr的内存空间置零,从从而完成初始化。

5.AF_INET就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。 一般来说,在各个系统中均定义成为0值。此处代表的意义是“任意地址”,即接受任意地址的连接请求。

6.htonl函数的功能是将十六位主机数转换成无符号长整型的网络字节顺序。

7.htons函数的功能是将十六位主机数转换成的网络字节顺序

8.Bind函数是在bind函数的基础上封装的函数,相比bind主要多了错误处理的功能,和上边的Socket类似。
如下:(仅供参考)
int Bind(int sockfd, struct sockaddr *my_addr, int addrlen){    int n;        if((n = bind(sockfd, my_addr, addrlen)) < 0)    {         printf("bind error\n");         exit(1);    }    return(n);}

9.Listen函数是在listen函数的基础上封装的函数,相比listen主要多了错误处理的功能,和上边的Socket类似。
如下:(仅供参考)
int Listen(int s, int backlog){    int n;    if((n = listen(s, backlog)) < 0)    {         printf("listen error\n");         exit(1);     }     return(n);}
listen函数用来等待参数s的socket连线。参数backlog指定能同时处理的最大连接要求,如果连接数目达此上限则client端收到ECONNREFUSED错误

10.Accept函数是在accept函数的基础上封装的函数,相比accept主要多了错误处理的功能,和上边的Socket类似。
如下:(仅供参考)
int Accept(int s, struct sockaddr * addr, int *addrlen){    int n;    if((n = accept(s, addr, addrlen)) < 0)    {        printf("accept socket error\n");        exit(1);    }    return(n);}
accept函数用来接受参数s的socket连线。参数s的socket必须先经bind()、listen()函数处理过,当有连线进来时accept()会返回socket处理代码,往后的数据传送使用accept()来接受新的连线要求。连线成功时,参数addr所指的结构会被系统填入远程主机的地址数据,参数addrlen为sockaddr的结构长度。关于结构sockaddr的定义请参考bind()。
通常情况下,服务器进程在accept调用中被投入睡眠,等待某个客户端连接的到达并被内核接受。TCP连接使用三次握手来建立连接。握手完毕时accept返回,其返回值是一个称为已连接描述符的新描述符。该描述符用于与新近连接的那个客户通信。accept为每个连接到服务器的客户返回一个新描述。

11.time函数取得系统目前的时间,需要头文件time.h,它在unp.h中包含了。函数会返回字公元1970年1月1日以来的秒数。

12.Write函数是经过封装的write函数,和上边的Accept()相类似。
如下:(仅供参考)
ssize_t Write(int fd, const void *buf, size_t count){    ssize_t n;        if( ( n = write(fd, buf, count)) < 0)    {         printf("write socket error\n");         exit(1);    }    return (n);}
Accept接受socket的连线请求,返回socket然后赋值给connfd,Write函数的调用就将buff缓冲区中的时间数据写入了connfd即socket中,传给了客户端程序。



0 0
原创粉丝点击