您的位置:首页 > 理论基础 > 计算机网络

网络编程之Introduction and TCP/IP(一)

2018-02-22 21:47 387 查看

写在最前

  APUE篇笔者的记录十分详细,但是UNP篇就不能如此了。因为很费时间,在UNP篇的记录将保留更多的英文原文,很多地方只是总括性的总结。

1. 基本概念

  如果是
Client
发起请求,则该编程方式不会太复杂,但是有时候也有
Server
发起请求到
Client
,这种属于异步回调通信。从
Server
的角度来看,一个
Server
同时和多个
Client
通信是很正常的事情。

  
Web Server
Client
的通信,使用
TCP
或者
UDP
协议,然后
TCP
协议使用
IP
协议,
IP
协议再和数据链路层进行通信。具体的形式如下图:



Note that the actual flow of information between the client and server goes down the protocol stack on one side, across the network, and up the protocol stack on the other side.

  有时候
Client
Server
在不同的局域网,然后这些局域网通过路由器连接到
WAN
。此时如下图所示:



Routers are the building blocks of WANs. The largest WAN today is the Internet.

2. A Simple Daytime Client

#include "unp.h"
int main(int argc, char **argv)
{
int sockfd, n;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr;
if (argc != 2)
err_quit("usage: a.out <IPaddress>");
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(13); /* daytime server */
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
err_quit("inet_pton error for %s", argv[1]);
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline
= 0; /* null terminate */
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
exit(0);
}


  以上程序特别强调一下几方面:

socket
函数创建一个套签字,这点在APUE17章中已经有所涉及。

使用
server
的IP地址和
daytime
对应端口号填充
sockaddr_in
结构体,设置地址种类为
AF_INET
,特别的调用了
htons
转换一个二进制端口号为合适的格式,
inet_pton
转化字符串IP地址为合适的格式,并将转换后的值填充
sockaddr_in
结构体的
sin_addr
成员。

connect
函数当用于TCP套签字时,将和
servaddr
指示的主机建立一个TCP连接。

NOTE :Everytime one of the socket functions requires a pointer to a socket address structure, that pointer must be cast to a pointer to a generic socket address structure.

TCP是一种字节流协议,其并没有明显的界线,所以如果使用一次
read
,并不能保证读取所有对方发送的数据,解决方式就是使用循环,当
read
返回0或者负数时,终止循环。

3. A Simple Daytime Server

#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); /* daytime server */
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);
}
}


  对于
Server
程序需要强调一下几点:

通过
bind
函数
daytime
的端口号和本机的接口地址被绑定到前面生产的套签字上。

通过调用
listen
监听
bind
之后的套签字,来获取来自client的请求。如果多个请求同时到达,由内核将这些请求放入队列中,等待处理。

当调用
accpet
时,该进程会被阻塞从而睡眠,等待来自
client
的请求,当一个
TCP
通信通过三次握手建立连接时,
accpet
函数返回一个新的套签字,该套嵌字已经和
client
建立连接。

client
调用
close
时,server结束该连接,这里涉及更具体的操作:

This initiates the normal TCP connection termination sequence: a FIN is sent in each direction and each FIN is acknowledged by the other end.

以上代码所展示的server属于
iterative server
,还有一种
concurrent server
,可以同时和多个client的连接通信,
Nginx
属于这种,最简单的实现方式就是为每个请求连接的client产生一个子进程,当然也可以用多线程来完成。

4. OSI Model



We consider the bottom two layers of the OSI model as the device driver and networking hardware that are supplied with the system.

The network layer is handled by the IPv4 and IPv6 protocols.The transport layers that we can choose from are TCP and UDP.

We show a gap between TCP and UDP indicate that it is possible for an application to bypass the transport layer and use IPv4 or IPv6 directly. This is called a raw socket, The upper three layers of the OSI model are combined into a single layer called the application.

First, the upper three layers handle all the details of the application (FTP, Telnet, or HTTP, for example) and know little about the communication details. The lower four layers know little about the application, but handle all the communication details: sending data, waiting for acknowledgments, sequencing data that arrives out of order, calculating and verifying checksums, and so on.

The second reason is that the upper three layers often form what is called a user process while the lower four layers are normally provided as part of the operating system (OS) kernel.

5. Discovering Network Topology

  两个实用工具:
netstat
ifconfig
.

netstat -i provides information on the interfaces. We also specify the -n flag to pri
b3fc
nt numeric addresses, instead of trying to find names for the networks. This shows us the interfaces and their names.

netstat -r shows the routing table, which is another way to determine the interfaces. We normally specify the -n flag to print numeric addresses. This also shows the IP address of the default router.

  使用
ifconfig
可以查询接口的详细信息:

This shows the IP address, subnet mask, and broadcast address. The MULTICAST flag is often an indication that the host supports multicasting. Some implementations provide a -a flag, which prints information on all configured interfaces.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: