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 --> 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.把server的众所周知的port捆绑到套接字
//使用 bzero 把套接字地址结构 servaddr 清零
//设置地址族为 AF_INET
//设置 IP 地址为 INADDR_ANY 。假设server主机骨多个网络接口。server进程就能够在随意网络接口上接受客户连接
//设置port号为 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 ( ; ; ) {
//server进程在 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
//由于本函数供server使用,所以还要加一个 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.server循环。 接受客户连接。发送应答
for ( ; ; ) {
len = sizeof(cliaddr);
//server堵塞在 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 server是迭代的。一次仅仅处理一个客户。大多数 TCP server是并发的。
并发最简单的技术是调用 fork 函数为每一个客户创建一个子进程。其它技术包含使用线程
取代 fork,或在server启动时预先 fork 一定数量的子进程
这部分的内容在我的其它博文 回射server程序 和 server程序设计范式 里有对应的代码演示样例
问题3:长时间执行
改善:daumon [todo]
UNIX网络编程卷1 时间获取程序server TCP 协议相关性的更多相关文章
- UNIX网络编程卷1 时间获取程序server UDP 协议无关
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie /** * UDP 协议无关 调用 getaddrinfo 和 udp_server **/ ...
- UNIX网络编程卷1 时间获取程序client TCP 使用非堵塞connect
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.当在一个非堵塞的 TCP 套接字(可使用 fcntl 把套接字变成非堵塞的)上调用 co ...
- UNIX网络编程卷1 时间获取程序client UDP 协议无关
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie /** * UDP.协议无关,调用 getaddrinfo 和 udp_client **/ ...
- 《UNIX网络编程 卷1》之"学习环境搭建"(CentOS 7)
<UNIX网络编程 卷1>的源码可以从www.unpbook.com下载得到.解压之后的目录为unpv13e. 详细步骤 编译 进入unpv13e目录,按如下步骤编译: ./configu ...
- [转载] 读《UNIX网络编程 卷1:套接字联网API》
原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网 ...
- UNIX网络编程 卷2:进程间通信
这篇是计算机类的优质预售推荐>>>><UNIX网络编程 卷2:进程间通信(第2版)> UNIX和网络专家W. Richard Stevens的传世之作 编辑推荐 两 ...
- Linux网络编程(简单的时间获取服务器)
1.一个简单的服务器时间获取程序 服务器和客户端采用UDP通信的方式,来编写一个简单的时间获取应用. 把过程大致理顺一下,首先是服务器端的编写,使用的是迭代的方式,没有并发 先创建一个socket而后 ...
- 《UNIX网络编程 卷1:套接字联网API》读书笔记(一):网络编程简介
概述 要编写通过计算机网络通信的程序,首先要确定这些程序相互通信所用的协议.大多数网络是按照划分成客户和服务器来组织的.本章及后续章节的焦点是TCP/IP协议族,也可称为网际协议族.下图为客户与服务器 ...
- 《Unix网络编程卷1:套接字联网API》读书笔记
第一部分:简介和TCP/IP 第1章:简介 第2章:传输层:TCP.UDP和SCTP TCP:传输控制协议,复杂.可靠.面向连接协议 UDP:用户数据报协议,简单.不可靠.无连接协议 SCTP:流控制 ...
随机推荐
- 内网穿透神器ngrok(转)
相信做Web开发的同学们,经常会遇到需要将本地部署的Web应用能够让公网环境直接访问到的情况,例如微信应用调试.支付宝接口调试等.这个时候,一个叫ngrok的神器可能会帮到你,它提供了一个能够在公网安 ...
- POJ 2442 Squence (STL heap)
题意: 给你n*m的矩阵,然后每行取一个元素,组成一个包含n个元素的序列,一共有n^m种序列, 让你求出序列和最小的前n个序列的序列和. 解题思路: 1.将第一序列读入seq1向量中,并按升序排序. ...
- 使用svnkit 的相关实例及相关问题汇总
SVNKIT操作SVN版本库的完整例子 http://www.cnblogs.com/wangjiyuan/p/svnkitwanchenglizi.html#!comments 2.SVNClien ...
- Android WebView挂马漏洞--各大厂商纷纷落马
本文章由Jack_Jia编写,转载请注明出处. 文章链接: http://blog.csdn.net/jiazhijun/article/details/11131891 作者:Jack_Jia ...
- 一步步学习Linux开发环境搭建与使用
00.Linux开发环境搭建与使用1--Linux简史 01.Linux开发环境搭建与使用2--Linux系统(ubuntu)安装方案 02.Linux开发环境搭建与使用3--通过虚拟机安装系统(ub ...
- codeforces 659B Qualifying Contest
题目链接:http://codeforces.com/problemset/problem/659/B 题意: n个人,m个区.给出n个人的姓名(保证不相同),属于的区域,所得分数.从每个区域中选出成 ...
- RBAC用户角色权限设计方案
RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用 户-角色 ...
- 在HTML中如何隐藏某段文字具体该怎么实现
<p style="display:none;"> 需要隐藏的文字....... </p> <div style="display:none ...
- [Cocos2d-x]节点之间的相互通讯
在做.NET开发时,对象之间的相互通讯一般使用事件(event)实现,事件概念是.NET对Delegate的封装. 在Cocos2d-x开发过程中,对象之间的通讯刚开始时不知道如何实现,于是想到c++ ...
- Android开发者必须深入学习的10个应用开源项目
Android 开发又将带来新一轮热潮,很多开发者都投入到这个浪潮中去了,创造了许许多多相当优秀的应用.其中也有许许多多的开发者提供了应用开源项 目,贡献出他们的智慧和创造力.学习开源代码是掌握技术的 ...