时间获取程序服务器 TCP 协议相关性

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

最初代码:

这是一个简单的时间获取服务器程序。它和时间获取程序客户端一道工作。

TCP/IPv4, IPv6 协议相关

IPv4 --> IPv6 (把代码中出现的左边的字符串换为右边的,就变成了IPv6版本的)

sockaddr_in --> sockaddr_in6

AF_INET --> AF_INET6

sin_family --> sin6_family

sin_port --> sin6_port

sin_addr --> sin6_addr

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

//1.创建 TCP 套接字  --> 为什么不检查一下创建成功还是失败呢 ?

// --> 大写字母开头的函数,如 Socket 是包裹函数,里面已经进行了错误处理

listenfd = Socket(AF_INET, SOCK_STREAM, 0);

//2.把服务器的众所周知的端口捆绑到套接字

//使用 bzero 把套接字地址结构 servaddr 清零

//设置地址族为 AF_INET

//设置 IP 地址为 INADDR_ANY 。如果服务器主机骨多个网络接口,服务器进程就可以在任意网络接口上接受客户连接

//设置端口号为 13

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

//3.把套接字转换为监听套接字

//这样才可以接受来自客户的外来连接

//LISTENQ 指定最大客户连接数

Listen(listenfd, LISTENQ);

//4.接受客户连接,发送应答

for ( ; ; ) {

//服务器进程在 accept 调用中被挂起,等某个客户连接的到达,完成 TCP 三次握手后 accept 才返回

connfd = Accept(listenfd, (SA *) NULL, NULL); //已连接描述符

ticks = time(NULL);

snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));

Write(connfd, buff, strlen(buff)); //把当前时间写给客户

//5.终止连接

// close 调用引发 TCP 连接终止序列。总共发送四个 TCP 分组。

// 每个方向一个 Fin,每个 Fin 又由各自的对端确认

Close(connfd);

}

}

问题1:协议相关

改善:使用 getaddrinfo 和 tcp_listen 来同时支持 IPv4 和 IPv6

/**

* TCP 协议无关,调用 getaddrinfo 和 tcp_listen

**/

#include "unp.h"

int

tcp_listen(const char *host, const char *serv, socklen_t *addrlenp)

{

int listenfd, n;

const int
on = 1;

struct addrinfo
hints, *res, *ressave;

//1.调用 getaddrinfo

//协议地址话为 AF_UNSPEC ,套接字类型为 SOCK_STREAM

//因为本函数供服务器使用,所以还要加一个 AI_PASSIVE 的标志

bzero(&hints, sizeof(struct addrinfo));

hints.ai_flags = AI_PASSIVE;

hints.ai_family = AF_UNSPEC;

hints.ai_socktype = SOCK_STREAM;

if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0)

err_quit("tcp_listen error for %s, %s: %s",

host, serv, gai_strerror(n));

ressave = res;

//2.尝试每个 addrinfo 结构直到成功或到达链表尾

do {

//创建套接字

listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

if (listenfd < 0)

continue;
/* error, try next one */

//设置套接字选项

Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

//绑定套接字

if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)

break;
//成功

//绑定失败,尝试下一个

Close(listenfd);

} while ( (res = res->ai_next) != NULL);

//3.检查是否失败

if (res == NULL)
//socket() 或 bind() 得到的 errorno

err_sys("tcp_listen error for %s, %s", host, serv);

//4.把套接字转换为监听套接字

Listen(listenfd, LISTENQ);

if (addrlenp)

*addrlenp = res->ai_addrlen;
/* return size of protocol address */

//5.调用 freeaddrinfo 清理由 getaddrinfo 返回的动态存储空间

freeaddrinfo(ressave);

//6.返回建立的监听套接字

return(listenfd);

}

/* end tcp_listen */

int

Tcp_listen(const char *host, const char *serv, socklen_t *addrlenp)

{

return(tcp_listen(host, serv, addrlenp));

}

/**

* TCP 协议无关,调用 getaddrinfo 和 tcp_listen

**/

#include "unp.h"

#include <time.h>

int

main(int argc, char **argv)

{

int listenfd, connfd;

socklen_t
len;

char buff[MAXLINE];

time_t
ticks;

struct sockaddr_storage
cliaddr;

//1.利用 Tcp_listen 得到监听套接字

if (argc == 2)

listenfd = Tcp_listen(NULL, argv[1], &addrlen);

else if (argc == 3)

listenfd = Tcp_listen(argv[1], argv[2], &addrlen);

else

err_quit("usage: daytimetcpsrv1 [ <host> ] <service or port>");

//2.服务器循环。接受客户连接,发送应答

for ( ; ; ) {

len = sizeof(cliaddr);

//服务器阻塞在 accept 调用,等待客户连接

connfd = Accept(listenfd, (SA *)&cliaddr, &len);

printf("connection from %s\n", Sock_ntop((SA *)&cliaddr, len));

//发送应答

ticks = time(NULL);

snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));

Write(connfd, buff, strlen(buff));

//关闭已连接套接字

Close(connfd);

}

}

问题2:一次只能处理一个客户

改善:大多数 UDP 服务器是迭代的,一次只处理一个客户。大多数 TCP 服务器是并发的。

并发最简单的技术是调用 fork 函数为每个客户创建一个子进程。其他技术包括使用线程

代替 fork,或在服务器启动时预先 fork 一定数量的子进程

这部分的内容在 回射服务器程序 里有相应的代码示例

问题3:长时间运行

改善: todo

时间: 2024-11-25 08:47:41

时间获取程序服务器 TCP 协议相关性的相关文章

UNIX网络编程卷1 时间获取程序server TCP 协议相关性

本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 最初代码: 这是一个简单的时间获取server程序.它和时间获取程序client一道工作. 它是 协议相关,把代码中出现的左边的字符串换为右边的,就变成了IPv6版本号的 IPv4 --> IPv6 sockaddr_in --> sockaddr_in6 AF_INET --> AF_INET6 sin_family --> sin6_family sin_port --&

时间获取程序客户端 TCP 协议相关性

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 最初代码: 这是一个简单的时间获取客户程序.客户与服务器建立一个TCP连接后,服务器以直观 可读格式简单地送回当前时间和日期 这个例子是协议相关,使用 inet_pton TCP/IPv4, IPv6 协议相关 IPv4 --> IPv6 (把代码中出现的左边的字符串换为右边的,就变成了IPv6版本的) sockaddr_in --> sockaddr_in6 AF_INET -->

时间获取程序服务器 UDP 协议无关

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie /** * UDP 协议无关 调用 getaddrinfo 和 udp_server **/ #include "unp.h" #include <time.h> int main(int argc, char **argv) { int sockfd; ssize_t n; char buff[MAXLINE]; time_t ticks; socklen_t le

时间获取程序客户端 TCP 使用非阻塞connect

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie /** * TCP,使用非阻塞 connect **/ #include "unp.h" int connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec) { int flags, n, error; socklen_t len; fd_set rset, wset; struct timeval t

时间获取程序客户端 UDP 协议无关

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie /** * UDP,协议无关,调用 getaddrinfo 和 udp_client **/ #include "unp.h" int udp_client(const char *host, const char *serv, SA **saptr, socklen_t *lenp) { int sockfd, n; struct addrinfo hints, *res, *

UNIX网络编程卷1 时间获取程序client TCP 使用非堵塞connect

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.当在一个非堵塞的 TCP 套接字(可使用 fcntl 把套接字变成非堵塞的)上调用 connect时. connect 将马上返回一个 EINPROGRESS 错误,只是已经发起的 TCP 三路握手继续进行. 接着使用 select 检測 这个连接是否建立成功 2.用途: 1)在TCP三路握手的时候进行其它处理 2)同一时候建立多个连接 3)使用 select 设置超时 /** * T

获取系统时间&amp;&amp;获取程序某一段执行时间

获取系统时间: CTime  _time; CString m_SystemTime("");  _time=CTime::GetCurrentTime();  m_SystemTime=_time.Format("%Y-%m-%d  %H:%M:%S"); 获取程序某一段执行时间: DWORD  betime(0),endtime(0),sumtime(0); int i=0; betime=GetTickCount(); while(i<10) {  Sl

Linux网络编程(简单的时间获取服务器)

1.一个简单的服务器时间获取程序 服务器和客户端采用UDP通信的方式,来编写一个简单的时间获取应用. 把过程大致理顺一下,首先是服务器端的编写,使用的是迭代的方式,没有并发 先创建一个socket而后bind服务器,绑定之后就可以创建一个循环来接收和发送 信息了,以达到和客户端之间的通信. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include

利用TCP协议实现通信

Socket的TCP通讯 一. socket的通讯原理 服务器端的步骤如下. (1)建立服务器端的Socket,开始侦听整个网络中的连接请求. (2)当检测到来自客户端的连接请求时,向客户端发送收到连接请求的信息,并建立与客户端之间的连接. (3)当完成通信后,服务器关闭与客户端的Socket连接. 客户端的步骤如下. (1)建立客户端的Socket,确定要连接的服务器的主机名和端口. (2)发送连接请求到服务器,并等待服务器的回馈信息. (3)连接成功后,与服务器进行数据的交互. (4)数据处