unix网络编程(笔记一)

一。

1.一个长时间运行的程序,即守护进程,它只在响应来自网络的请求时才发送网络消息。

2.通常一个客和每次只与一个服务器通信,不过以web浏览器为例子,该客户端程序却可以与多个不同的web服务器通信。

3.tcp/ip 协议簇 ,也称为“网际协议簇“

4.英特网 和 网际网

 *因特网是一个网际网

 *网际网是采用tcp/ip协议通信所连通的网络。

 *因特网只有一个,全球具有地址唯一性。不属于因特网的网际是可以是任何一个节点分配地址。

 *一个进程关闭会关闭它所打开的所有描述符(文件、socket、pipe等),即将结束的程序,也可以不close(fd)的。不过通常我们都close()

5.bzero 比 memset 更好记忆。 因为memset参数如果搞乱了,memset都检查不出来,因为都是int类型。bzero(&add, sizeof(add) );

6.inet_pton() 支持ipv6的ip地址转换器。 inet_add()旧的。

7.之所以ip要使用通用的struct sockaddr* ,是因为套接字函数早于ANSIC标准,void*还不可用,否则我们可以用void*表示任何数据结构。

8.tcp是一个没有字符边界的字节流,源源不断,udp则有其数据边界结尾。

9.tcp传输层的数据单元叫分节,如果分节大于发送缓冲区,则分段进行发送。

1.read()不能确保一次性能读完all the data,所以我们应确保它能在循环中一直读取数据直到read返回0或负值才结束对数据的接收读取。

 对于客户端:服务器close(fd)表示数据结束

 对于服务端:客户端close(fd)表示数据发送完毕或请求结束。

errno值不应该用于多线程的全局变量来记录。因为是多线程的。嘻嘻

2.unix在一个进程终止时总是关闭该进程所有打开的描述符。

3.传输层:分节 , 网路层:ip数据报,链路层:祯,物理层:bit传输咯。  除了物理层,这些单元是越来越大呀。

4.tcp/ip协议族,为提高效率,应尽可能避免ip的分层与重组操作。

5.ipv4数据报最大65535,ipv6最大65575

避免被另一个函数集细节把网络编程讨论搞负杂了。

6.错误处理:包裹函数。 它很少是程序性能的瓶颈所在。

7.每个包裹函数完成实际的函数调用,检查返回值,并在发生错误时终止进程。大写开头的函数。

8.线程函数出错时并不把错误返回给主调,而是通过设置errno值返回。

9.INADDR_ANY表示多个网络接口和主机进程可以在任意网络接口上接受客户链接

1.snprintf() 比 sprintf()要好,因为sprintf()不检查缓冲区溢出。fgets, strncat ,strncpy,strlcat, strlcpy

2.size_t类似的数据类型的定义,其实是为了更好的融合32,64位机,为了可移植性嘛

二。

*传输层tcp ,udp,sctp ,udp是一个无连接的协议哦。

1.udp:每个数据都有一个长度,该长度随数据一起发送到目标端。因为他是无连接的。

  udp每发送一个数据包都会创建链接,发送,释放链接。如果udp调用connect的话呢,那么内核就记住第一次对端的ip/port,这样之后就不需要总是创建和释放链接,直接发送数据即可。

2.tcp . 1  对 多 , udp. 多 对 多

3.tcp如果没有收到确认,就自动重传并延长等待时间。

4.流量控制--》通告窗口:接收缓冲的容量

5.ipv4 32位,ipv6 128位

6.3次握手:

 1.客发syn j

 2.服回ack , syn j+1

 3.客回ack j+1+1

7.tcp选项:

 1.最大分节大小:TCP_MAXSEG

 2.最大窗口大小:SO_RCVBOF

四次终止:

close() ------> fin,j

<-----ACK j+1

<------FIN,n

------->ACK n+1; (time_waite为了处理该ack丢失的情况)

主动发起close的在这里进入time_wait状态,因为他要确保对面的挂,他要保证万一这个ack在途中阻塞等一系列情况,让ack到达对方,避免过期。然后他自己会过一段时间挂掉。

8.TCP状态转换:

CLOSE-------------------------LISTEN

SYN_SEND--------------------SYN_RCVD

ESTABLISHED----------------ESTABLISHED

FIN_WAITE_1------------------------CLOSE_WAITE

FIN_WAITE_2-------------------------LAST_ACK

TIME_WAITE--------------------------CLOSED

CLOSED

9.       2MSL最大分节生命期的2倍时长,msl在因特网中存活最长的ip数据报。

1.全双工:是两条独立的链接,并非一条共用的来回链接。

三。

1.端口号:

*端口号可以区分进程使用的多种不同的协议tcp,udp

* 0--1023 属于进程端口

* 1024---49151已登记端口号:用来给服务端程序使用

* 49152--65535动态端口号:给客户程序的临时端口号

2.标识每个端点的两个值(ip,端口对)通常称为一个套接字。 4元素才能确定消息目标与起始。

3.tcp必须为已发送的数据保留一个副本。直到他被对端确认为止。。。。然后才丢弃。

4.udp是不可靠的,因此无需缓冲区。

5.write成功仅仅表示:数据已成功加入到链路层的输出队列,并不代表对方接收成功。

6.主动执行关闭的那一端,是历经TIME_WAIT状态的那一端。 -------- 为了处理最终的哪一个ACK丢失的情况。

四。

基本套接字编程

1.tcp,udp的ip与port在套接字地址结构中总是以网络字节序来存储的。

2.地址结构:内核会把地址先转成struct sockaddr *,通用结构再取出其中sa_family字段来确定是哪种类型的地址。

3.从进程到内核传递套接字地址结构的函数有3个:bind  , connect , sendto 

4.内核 到 进程  :accept recvfrom getsockname getpeername

5.字节排序:小端 大端 ----》网络字节序列。主机字节序列。

6.在大端系统中,这些字节排序函数通常被定义为空宏。 htons htonl ntohs ntohl()

7.客户端不用bind(),内核则会确定源地址,且会选择一个临时端口。

8.调getsockname()可得到临时端口信息。

9.Listen().内核为任何一个给定的监听套接字维护两个队列:未完成链接的队列,已完成链接的队列。

1.accept()第二、三个参数为空指针表示我们对客户不关心。 (0---1023端口的bind必须以root身份bind)

2.close(fd) 仅仅是引用计数减1罢了。直到0才真正释放。

3.getsockname()本地信息,getpeername()外地信息 (ip,port)

4.一个信号处理函数运行期间,正被递交的信号是阻塞的。

5.如果一个信号在被阻塞期间产生了一次或多次,那么该信号被解阻塞后,通常只递交一次:信号默认是不排队的。

6.unix关机时,init进程会给所有进程发送sigterm信号以关闭,过一段时间再发sigkill信号;sigkill信号是无法被捕获的。

7.以文本串方式传递数据会比较好,因为客----服 就解释二进制序列不一致。因为小端大端不同的问题导致。

8.I/O复用,处理多个描述符select() poll(),不因为一个描述符而阻塞其他描述符的数据交流。

9.输入操作:1.等待数据准备好 2.从内核向进程复制数据。进程----》内核复制

*阻塞I/O

*非阻塞I/O

*I/O复用

信号驱动式I/O模型----由信号来处理

异步I/O模型------------告之内核处理,处理完了让它通知过来/。

五。

*套接字选项

1.fcntl()设置非阻塞 或 信号驱动式I/o,设置属性

2.getsockopt() setsockopt()

3.Tcp已连接套接字会从监听套接字继承过来。

4.fcntl:235page or 183page . 

常用的选项:SO_keepalive so_rcvbuf so_sndbuf so_reuseaddr

六。

UDP套接字编程 187

sendto() recvfrom()

一般来说,大多数tcp服务器是并发的,udp是迭代的。

2.udp的connect()能够提高效率,避免每个包都建立链接和释放链接。

七。

名字与地址转换:

gethostbyname() gethostbyaddr(0 getserverbyname() getserverbyport() getaddrinfo() getnameinfo()





你可能感兴趣的:(unix网络编程(笔记一))