[心得]UNP知识整理

Unix网络编程是一本系统编程的经典书籍。这里整理了相关知识。

#include    "unp.h"

int
main(int argc, char **argv)
{
    int                 sockfd, n, counter = 0;
    char                recvline[MAXLINE + 1];
    struct sockaddr_in  servaddr;

    if (argc != 2)
        err_quit("usage: a.out ");

    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) {
        counter++;
        recvline[n] = 0;    /* null terminate */
        if (fputs(recvline, stdout) == EOF)
            err_sys("fputs error");
    }
    if (n < 0)
        err_sys("read error");

    printf("counter = %d\n", counter);
    exit(0);
}

这里的做法有一个缺陷,就是它和协议耦合在一起。

约定包裹函数名的首字母大写。
SCTP:流控制传输协议
ICMP:网际控制消息协议

TCP三路握手:建立连接
1. 服务器调用socketbindlisten被动打开连接
2. 客户调用connect主动打开,发送SYN同步
3. 服务器返回ACK+SYN给客户
4. 客户确认SYN

TCP中执行主动关闭时会经历TIME_WAIT状态。这个状态是为了实现TCP全双工连接终止(处理最终那个ACK丢失的情况),并允许老的重复分节从网络中消逝。
最长分节生命期MSL是任何IP数据报在因特网上存活的最长时间。

TCP使用4分组交换序列终止连接。

inet_aton
inet_addr
inet_ntoa
在点分十进制数串与它长度为32位的网络字节序二进制值间转换ipv4地址。
inet_pton
inet_ntop
通用p:presentation和numeric

读写socket字节流:
ssize_t readn(int filedes, void *buff, size_t nbytes);
ssize_t written(int filedes, const void *buff, size_t nbytes);
ssize_t readlineint filedes,void *buff,size_t maxlen);

socket head file:
#include 

创建套接字
int socket(int family, int type, int protocol);
连接
int connect(int sockfd, const struct sockaddr *servaddr, sockelen_t addrlen);

int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);

int listen(int sockfd, int backlog);

int accept(int sockfd, struct socketaddr *cliaddr, socklen_t *addrlen);

int close(int sockfd);

最流行的I/O模型是阻塞式的
select函数允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生或经历一段指定时间后唤醒它。
#include 
#include 

int select(int maxfdpl,df_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);

终止网络连接的close函数有2个限制:
1.close把描述符-1,仅在该计数变回0时才关闭套接字。
2.close终止读和写两个方向的数据传送。
shutdown可以避免这两点:
int shutdown(int sockfd, int howto);

poll函数类似select函数,但提供额外信息
#include 
int poll(struct pollfd *fdarray, unsigned long nfds, int timeout);

域名系统DNS在主机名和ip地址之间做映射。
#include 
查找主机名
按名
struct hostent *gethostbyname(const char *hostname);
按地址
struct hostent *gethostbyaddr(const char *addr, socklen_t len, int family);
查找服务
按名
struct servent *getservbyname(const char *servname, const char *protoname);
按端口
struct servent *getservbyport(int port, const char *protoname);

getaddrinfo函数能处理名字到地址以及服务到端口这两种转换。返回的是一个sockaddr。
int getaddrinfo(const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result);

void freeaddrinfo(struct addrinfo *ai);
释放资源

getnameinfo是getaddrinfo的补充,它以套接字地址为参数,返回描述其中主机的一个字符串和描述其中服务的另一个字符串。
int getnameinfo(const struct sockaddr *sockaddr, socklen_t addrlen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags);

守护进程是在后台运行且不与任何控制终端关联的进程。
在守护进程中记录消息的常用技巧就是调用syslog函数
#include 

void syslog(int priority, const char *message,...);

可能阻塞的套接字调用包括以下4类:
1.输入操作,read,readv, recv,recvfrom, recvmsg
2.输出操作,write,writev, send, sendto,sendmsg
3.接受外来连接,accept函数
4.发起外出连接,connect函数

网络程序,特别是服务器程序,经常在程序启动执行后使用ioctrl获取所在主机全部网络接口的信息,包括接口地址,是否支持广播,是否支持多播等。

#include 

int ioctl(int fd, int request,...);

网络相关的request划分为6类:
套接字操作(是否位于带外标记)
文件操作(设置或清除非阻塞标志)
接口操作(返回接口列表,获取广播地址)
ARP高速缓存操作(创建,修改,获取或删除)
路由表操作(增加或删除)
流系统

使用sysctl可以检查路由表和接口列表的进程却不限用户权限。

#include 
#include 

int sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);

广播发送的数据报由发送主机某个所在子网上的所有主机接收。广播的劣势在于同一子网上的所有主机都必须处理数据报。

TCP没有真正的带外数据,不过提供紧急模式和紧急指针。带外数据未广泛使用,telnet和rlogin使用它。它们使用带外数据是为了统治远端有异常情况发生,而且服务器丢弃带外标记前接收所有输入。

信号驱动式I/O就是让内核在套接字上发生“某事”时使用SIGIO信号通知进程。

你可能感兴趣的:(技术笔记)