《UNIX网络编程 卷1:套接字联网API》读书笔记(一):网络编程简介
概述
要编写通过计算机网络通信的程序,首先要确定这些程序相互通信所用的协议。大多数网络是按照划分成客户和服务器来组织的。本章及后续章节的焦点是TCP/IP协议族,也可称为网际协议族。下图为客户与服务器使用TCP在同一个以太网中通信:

图1.1 客户与服务器使用TCP在同一个以太网进行通信
同一网络中的客户机与服务器无需出于同局域网,上图1.1所示的是同一个局域网。下图1.2所示的是处于不同局域网的客户机与服务器,这两个局域网通过使用路由器连接到广域网。

图1.2 出于不同局域网的客户主机与服务器主机通过广域网进行连接
如今讨论Unix是经常使用POSIC一词,它是一种被多数厂商采纳的标准。
一个简单的时间获取客户程序
// 该头文件包含了大部分网络程序都需要的许多系统头文件
#include "unp.h" // main函数定义,其形式参数就是命令行参数
int
main(int argc, char **argv)
{
int sockfd, n;
char recvline[MAXLINE + ];
struct sockaddr_in servaddr; if (argc != )
err_quit("usage: a.out <IPaddress>"); // socket函数创建一个网际(AF_INET)字节流(SOCK_STREAM)套接字,该函数返回一个小整数描述符。如果socket函数调用失败,调用err_sys函数放弃程序运行
if ( (sockfd = socket(AF_INET, SOCK_STREAM, )) < )
err_sys("socket error"); // 把IP地址和端口号填入一个网际套接字地址结构(一个名为servadrr的sockdrr_in结构变量),使用bzero把整个结构清零
bzero(&servaddr, sizeof(servaddr));
// 置地址族为AF_INET,端口号为13,IP地址为第一个命令行参数的值(argv[1])
// 网际套接字结构中IP地址和端口号必须使用特定格式,为此调用库函数htons去转换二进制端口号,又调用inet_pton去把ASCII命令行参数转换为合适的格式
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(); /* daytime server */
if (inet_pton(AF_INET, argv[], &servaddr.sin_addr) <= )
err_quit("inet_pton error for %s", argv[]); // connect函数应用于TCP套接字时,将由它的第二个参数指向套接字地址结构指定的服务器建立一个TCP连接
// 套接字地址结构的长度必须作为该函数的第三个参数指定
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < )
err_sys("connect error"); // 使用read函数读取服务器的应答,并用标准I/O函数fputs输出结果
// 把read放在循环以便读取完数据,当read返回0或者负数时终止循环
while ( (n = read(sockfd, recvline, MAXLINE)) > ) {
recvline[n] = ; /* null terminate */
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (n < )
err_sys("read error"); // 终止程序运行
exit();
}
我们从官网www.unpcook.com下载源代码unpv13e.tar.gz。解压后进入文件夹。我的是Ubuntu系统。根据文件夹中Readme的提示输入相应的命令。
redhat@redhat-virtual-machine:~/桌面/unpv13e$ ./configure redhat@redhat-virtual-machine:~/桌面/unpv13e$ cd ./lib
redhat@redhat-virtual-machine:~/桌面/unpv13e/lib$ make redhat@redhat-virtual-machine:~/桌面/unpv13e$ cd ./libfree
redhat@redhat-virtual-machine:~/桌面/unpv13e/libfree$ make
// 如果报错如下,则需要在当前目录下打开inet_ntop.c文件
// 将第60行的size_t size修改为socklen_t size 然后保存
// 重新输入make后不报错即可 gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o inet_ntop.o inet_ntop.c
inet_ntop.c: In function ‘inet_ntop’:
inet_ntop.c::: error: argument ‘size’ doesn’t match prototype
size_t size;
^
In file included from inet_ntop.c:::
/usr/include/arpa/inet.h::: error: prototype declaration
extern const char *inet_ntop (int __af, const void *__restrict __cp,
^
make: *** [inet_ntop.o] Error redhat@redhat-virtual-machine:~/桌面/unpv13e/libfree$ cd ../libgai
redhat@redhat-virtual-machine:~/桌面/unpv13e/libgai$ make
// 以下的warning不用理会
/usr/include/arpa/inet.h: In function ‘inet_ntop’:
inet_ntop.c::: warning: ‘best.len’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if (best.base == - || cur.len > best.len)
^
inet_ntop.c::: note: ‘best.len’ was declared here
struct { int base, len; } best, cur;
^
gcc -I../lib -g -O2 -D_REENTRANT -Wall -c -o inet_pton.o inet_pton.c
ar rv ../libunp.a in_cksum.o inet_ntop.o inet_pton.o
a - in_cksum.o
a - inet_ntop.o
a - inet_pton.o
ranlib ../libunp.a // 用root权限将以上编译生成的libunp.a 文件复制到/usr/lib目录中 redhat@redhat-virtual-machine:~/桌面/unpv13e/libgai$ cd ..
redhat@redhat-virtual-machine:~/桌面/unpv13e$ sudo cp libunp.a /usr/lib
[sudo] redhat 的密码: // 打开unp.h文件将其中的#include "../config.h" 改成 #include "config.h"
redhat@redhat-virtual-machine:~/桌面/unpv13e$ vim lib/unp.h // 进入intro目录编译客户端文件并用root权限运行
redhat@redhat-virtual-machine:~/桌面/unpv13e$ cd intro/
redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ make daytimetcpcli
redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ sudo ./daytimetcpcli 127.0.0.1
// 错误提示无法连接
connect error: Connection refused // 我们先打开服务器
redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ make daytimetcpsrv
redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ sudo ./daytimetcpsrv // 然后再打开另一个终端,在那里再运行客户端即可
redhat@redhat-virtual-machine:~/桌面/unpv13e/intro$ sudo ./daytimetcpcli 127.0.0.1
[sudo] redhat 的密码:
Mon Dec ::
上面提到了客户端获取时间的程序代码,下面为服务器端的程序。
#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, ); // 填写一个网际套接字地址结构并调用bind函数,把服务器的端口捆绑到所创建的套接字中 bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(); /* daytime server */ Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); // 调用listen函数把该套接字转换成一个监听套接字,使来自客户端的连接可以在该套接字上由内核接受
// socket、bind、listen这三个函数调用步骤是任何tcp服务器准备监听描述符的正常步骤
// LISTENQ定义在头文件中,它指定系统内核允许在这个监听描述副符上排队的最大客户连接数 Listen(listenfd, LISTENQ); // 服务器进程在accept调用中被投入睡眠,等待客户的连接
// TCP连接的三次握手完毕时accept返回,其返回值是一个被称为已连接描述符的新描述符
for ( ; ; ) {
connfd = Accept(listenfd, (SA *) NULL, NULL); // time函数获取当前时间,ctime函数把时间转换成直观可读的时间格式
ticks = time(NULL); // snprintf函数在这个字符串末尾添加一个回车符和一个换行符
// write函数把结果字符串写给客户 snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(connfd, buff, strlen(buff));
// 终止连接
Close(connfd);
}
}
《UNIX网络编程 卷1:套接字联网API》读书笔记(一):网络编程简介的更多相关文章
- Unix网络编程--卷一:套接字联网API
UNIX网络编程--卷一:套接字联网API 本书面对的读者是那些希望自己编写的程序能够使用成为套接字(socket)的API进行彼此通信的人. 目录: 0.准备环境 1.简介 2.传输层:TCP.UD ...
- [转载] 读《UNIX网络编程 卷1:套接字联网API》
原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网 ...
- 《Unix网络编程卷1:套接字联网API》读书笔记
第一部分:简介和TCP/IP 第1章:简介 第2章:传输层:TCP.UDP和SCTP TCP:传输控制协议,复杂.可靠.面向连接协议 UDP:用户数据报协议,简单.不可靠.无连接协议 SCTP:流控制 ...
- VC++学习之网络编程中的套接字
VC++学习之网络编程中的套接字 套接字,简单的说就是通信双方的一种约定,用套接字中的相关函数来完成通信过程.应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问 ...
- Linux网络编程:原始套接字简介
Linux网络编程:原始套接字编程 一.原始套接字用途 通常情况下程序员接所接触到的套接字(Socket)为两类: 流式套接字(SOCK_STREAM):一种面向连接的Socket,针对于面向连接的T ...
- 网络编程与socket套接字
网络编程与socket套接字 传输层 PORT协议 port是一种接口,数据通过它在计算机和其他设备(比如打印机,鼠标,键盘或监视器)之间,网络之间和其他直接连接的计算机之间传递 TCP协议 传输 ...
- Python黑帽编程2.8 套接字编程
Python黑帽编程2.8 套接字编程 套接字编程在本系列教程中地位并不是很突出,但是我们观察网络应用,绝大多数都是基于Socket来做的,哪怕是绝大多数的木马程序也是如此.官方关于socket编程的 ...
- Python网络编程之TCP套接字简单用法示例
Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...
- [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]
[网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...
随机推荐
- 从VGA到GPU!细数二十年显卡发展历程
VGA有很多层涵义,本来是用于代表一个分辨率(您可能不了解VGA,但应该知道QVGA代表什么),随后被普遍称为显示输出接口.为了输出VGA分辨 率.提供VGA输出接口,显卡和VGA就有了不解之缘,显卡 ...
- Netty高可靠性设计:优化建议
尽管Netty的可靠性已经做得非常出色,但是在生产实践中还是发现了一些待优化点,本小节将进行简单说明.希望后续的版本中可以解决,当然用户也可以根据自己的实际需要决定自行优化. 1 发送队列容量上限控 ...
- org.apache.jasper.JasperException
1.错误描述 2014-7-13 17:20:50 org.apache.catalina.core.StandardWrapperValve invoke 严重: Servlet.service() ...
- Angular21 动态绑定CSS样式
1 需求 在前端开发中通常需要动态对某些元素的样式进行动态设定,传统的CSS绑定分为CSS类绑定和Style样式绑定:在Angular中利用相关指令同样可以完成CSS类绑定和CSS样式绑定 2 内置指 ...
- hihocoder Challenge 29 A.序列的值
我现在就感觉我这人现在真的没有dp的意识 其实真写起来也不难,但是把就是练的少思维跟不上,dp从根本上就是一种状态的提炼和聚集. 按照题解的意思来,表示二进制第i位的值为j(0,1)的组合有多少,然后 ...
- 2016四川省赛 Floyd-Warshall
这题真的有毒 首先你忽略 N-M < 100 的条件你就gg吧 其次就算你知道了怎么做之后 还有可能因为写vector或者各种常数大的原因被卡 #include<iostream> ...
- 更改Qt Application为 Qt Console Application
工程属性 -> 链接器 -> 系统 -> 子系统 : 更改为 控制台 (/SUBSYSTEM:CONSOLE)
- 校园网IPv6加速
对于广大学生来说,上网是一件很纠结的事情,校园网要么按时间计费,要么按流量计费,要么是校园宽带.按时间计费速度慢,按流量计费费用高,校园宽带还不能共享,只能电脑开热点给手机上网.有没有既能提高网速又经 ...
- iOS - MySQL 的安装配置
前言 提前下载好相关软件,且安装目录最好安装在全英文路径下.如果路径有中文名,那么可能会出现一些莫名其妙的问题. 提前准备好的软件: mysql-5.7.17-macos10.12-x86_64.dm ...
- java——基础语法
java基础语法 1.关键字:java赋予特殊含义的单词. 2.标识符:程序中开发人员自定义的名词,例如:类名,函数名,变量名(注意事项:①不能以阿拉伯数字开头②不能采用关键字). 3.常量:固定的数 ...