网络编程核心考点

第一章

1. 分层

  • 主机-网络层:负责物理层和网络层的数据转换
  • 互连网络层:网络之间的数据传输
    • IP协议:尽力而为、不可靠、无连接
  • 传输层:进程之间的端到端数据传输
  • 应用层

2. TCP工作流程

  • 建立连接-传输数据-断开连接
  • 状态之间的转换,三次握手,四次挥手。
  • TIME_WAIT存在的两个理由就是:
    • 可靠地实现TCP全双工连接的终止;
    • 允许老的重复分节(数据报)在网络中消逝。

3. 服务器的分类

  • 按照使用的传输协议不同可以分为无连接的服务器与面向连接的服务器;
  • 按照是否维护与客户交互活动的信息可以分为有状态服务器与无状态服务器;
  • 按照处理与客户交互的机制不同又可以分为循环服务器与并发服务器。

4. 字节序

  • 主机字节序:小尾字节序(小存小)
  • 网络字节序:大尾字节序(小存大)

5. 套接字类型

  • 流式套接字:SOCK_STREAM、TCP
  • 数据报式套接字:SOCK_DGRAM、UDP
  • 原始套接字:SOCK_RAW

6. 重点函数

  • 字节序之间的转换:htonl()、htons()、ntohl()和ntohs()
  • 清空函数:memset()清空一个结构类型的变量或数组
    • int buf[50];
    • memset(buf, 0, 50*sizeof(int))
  • strcmp()函数:比较两个字符串的大小
  • atoi()函数:字符串转换成整型数值

7. 特殊端口

  • FTP:21
  • HTTP:80
  • POP3:110
  • SMTP:25
  • DNS:53
  • TFTP:69
  • SNMP:161

第二章

1. 函数

  • socket(int domain,int type,int protocol)
    • (协议组,套接字类型,协议号)
    • TCP:socket(PF_INET,SOCK_STREAM,0)
    • UDP:socket(AF_INET,SOCKET_DGRAM,0)
  • connect(int sockfd,struct sockaddr* serv_addr,int addrlen)
    • (套接字描述符,服务器地址指针,地址长度大小)
    • connect(csock,(struct socketaddr*)&servaddr,sizeof(struct sockaddr))
  • bind(int sockfd,struct sockaddr *my_addr,int addrlen)
    • (套接字描述符,本机的地址,地址长度大小)
    • bind(ssock,(struct sockadr*)&servaddr,sizeof(strucr sockaddr))
  • listen(int sockfd,int backlog)
    • (套接字描述符,队列大小)
    • listen(ssock,10)
  • accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
    • (套接字描述符,客户机地址,地址长度大小)
    • accpet(ssock,(struct sokaddr*)&clientaddr,sizeof(struct sockaddr))
  • send(int s, const void *buf, size_t len, int flags)
    • (套接字描述符,要发送的数据,数据长度,方式)
    • send(sock,buffer,strlen(buffer),0)
  • recv(int s, void *buf, int len, unsigned int flags)
    • (套接字描述符,存放接收数据的缓冲区,数据长度,方式)
    • recv(sock,buffer,strlen(buffer),0)
  • sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen)
    • (套接字描述符,要发送的数据,方式,数据长度,主机地址,地址长度大小)
    • send(sock,buffer,strlen(buffer),(struct sockaddr*)&addr,siezof(struct sockaddr))
  • recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen)
    • (套接字描述符,存放接收数据的缓冲区,数据长度,方式,主机地址,地址长度)
    • recvfrom(sock,buffer,strlen(buffer),0,(struct sockaddr*)&addr,seizof(struct sockaddr))

2. 流程加函数

TCP服务器设计流程

  • 调用socket()函数创建服务器套接字
    • TCP:int ssock=socket(PF_INET,SOCK_STREAM,0)
  • 调用bind()函数绑定本地端点地址
    • bind(ssock,(struct sockaddr*)&servaddr,sizeof(struct sockaddr) “这里可以写成(sizeof(servaddr)” )
  • 调用listen()将套接字设为被动模式,并设置等待队列长度
    • listen(ssock,10)
  • 调用accept()函数等待连接
    • accept(ssock,(struct sockaddr*)&clientaddr,sizeof(clientaddr))
  • 调用recv()函数接收数据
    • recv(ssock,buffer,strlen(buffer),0)
  • 调用send()函数发送数据
    • send(ssock,buffer,strlen(buffer),0)
  • 调用close()函数关闭套接字
    • close(ssock)

TCP客户端设计流程

  • 调用socket()函数创建服务器套接字
    • TCP:int csock=socket(PF_INET,SOCK_STREAM,0)
  • 调用connect()函数连接服务器
    • connect(csock,(struct sockaddr*)&servaddr,sizeof(servaddr))
  • 调用recv()函数接收数据
    • recv(csock,buffer,strlen(buffer),0)
  • 调用send()函数发送数据
    • send(csock,buffer,strlen(buffer),0)
  • 调用close()函数关闭套接字
    • close(csock)

UDP服务器设计流程

  • 调用socket()函数创建服务器套接字
    • UDP:int ssock=socket(AF_INET,SOCKET_DGRAM,0)
  • 调用bind()函数绑定本地端点地址
    • bind(ssock,(struct sockaddr*)&servaddr,sizeof(struct sockaddr))
  • 调用recvfrom()函数接收数据
    • recvfrom(ssock,buffer,strlen(buffer),0,(struct sockaddr*)&clientaddr,sizeof(clientaddr))
  • 调用sendto()函数发送数据
    • sendto(ssock,buffer,strlen(buffer),0,(struct sockaddr*)&clientaddr,sizeof(clientaddr))
  • 调用close()函数关闭套接字
    • close(ssock)

UDP客户端设计流程

  • 调用socket()函数创建服务器套接字
    • UDP:int csock=socket(AF_INET,SOCKET_DGRAM,0)
  • 调用recvfrom()函数接收数据
    • recvfrom(csock,buffer,strlen(buffer),0,(struct sockaddr*)&servaddr,sizeof(servaddr))
  • 调用sendto()函数发送数据
    • sendto(csock,buffer,strlen(buffer),0,(struct sockaddr*)&servaddr,sizeof(servaddr))
  • 调用close()函数关闭套接字
    • close(csock)

3. Windows下的套接字编程

Windows下的套接字编程流程与Linux是相似的

  • 使用WSAStartup()函数初始化WinsockDLL
  • 关闭套接字函数改为closesocket()
  • 最后调用WSACleanup()函数接数Winsock Socket API

第三章

1. 设计流程加函数

TCP服务器设计流程

/**
*详细介绍和单次服务器相同
*客户端设计与单次相同(整体放进循环体并设计结束条件)
*/
socket(...);
bind(...);
listen(...);
while(1)
{
 accept() (...);
 process(...);
 close(...);
}
close(...);

UDP服务器设计流程

/**
*详细介绍和单次服务器相同
*客户端设计与单次相同(整体放进循环体并设计结束条件)
*/
socket(...);
bind(...);
while(1)
{
 recvfrom(...);
 process(...); 
 sendto(...);
}
close(…);

第四章

1. 差别

  • 循环服务器是指服务器在同一时刻只可以响应一个客户端的请求的服务器
    • 设计、编程、调试和修改简单的优点
    • 用户对时间要求低
  • 并发服务器就是指在同一个时刻可以处理来自多个客户端的请求的服务器
    • 各个请求所需要的处理时间差别非常大
    • 在一台多处理器的计算机上运行

2. 进程、线程各自的优缺点

  • 进程优点:编程、调试简单,可靠性较高。
  • 进程缺点:创建、销毁、切换速度慢,内存、资源占用大。
  • 线程优点:创建、销毁、切换速度快,内存、资源占用小。
  • 线程缺点:编程、调试复杂,可靠性较差。
  • 进程只是资源分配的单位,而真正可以在处理器(CPU)上独立调度运行的基本单位是线程。

3. 重点函数及使用

fork()函数:创建一个新进程

  • 若fork()函数调用成功,则在子进程中其返回值为0,而在父进程中其返回值为子进程的进程号(进程ID)

  • 若fork()函数调用不成功,则在父进程中其返回值为-1

     /**
     *两种方式
     */
     int pid;
     pid = fork();  //调用fork()函数创建一个新进程
     if(pid == -1 ) 
     {  //若调用fork()函数出错
      perror ("fork failed!"); 
      exit(1);
     } 
     else if( pid = =0 ) 
     {  //以下是子进程所执行的操作
      printf("This is the child process!"); 
     } else 
     {  //以下是父进程所执行的操作
      printf("This is the parent process!"); 
     }
    
     int pid;
     pid=fork();
     switch (pid) {
     case -1: //若调用fork()函数出错
     perror("fork failed!");
     exit(1); 
     case 0: //以下是子进程所执行的操作
     printf("This is the child process!");
     break;
     default: //以下是父进程所执行的操作
     printf("This is the parent process!");
     break;
     }
    
  • getpid()函数:获得当前进程的进程号

  • getppid()函数:获得当前进程的父进程的进程号

  • wait()函数:进程一旦调用了wait()函数,就立即阻塞自己

    • WIFEXITED:等待子进程如果结束返回非0值
    • WEXITSTATUS:等待子进程结返回子进程由exit()返回的结束代码
    • WIFSIGNALED:等待子进程如果信号结束返回非0值
    • WTERMSIG:若子进程因为信号结束则利用该宏可获得子进程的中止信号代码
    • WIFSTOPPEN:子进程处于暂停执行状态则该宏将返回非0值
    • WSTOPSIG:若子进程处于暂停状态则利用该宏可获得引发子进程暂停的信号代码
  • waitpid()函数:pid_t waitpid(pid_t pid, int *status, int options)

    • pid:
      • pid>0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid()就会一直等下去。
      • pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid()和wait()的作用完全等同。
      • pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid()不会对它做任何理睬。
      • pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。
        -status:用来保存被收集进程退出时的一些状态,是一个指向int类型的指针
    • options:
      • options置为WUNTRACED,则当子进程处于暂停状态,waitpid()将马上返回;
      • options置为WNOHANG,则即使没有子进程退出,waitpid()也将立即返回;
      • options置为0,则waitpid()会像wait()那样阻塞父进程,直到所等待的子进程退出
    • signal()函数用法:signal(SIGALRM, handler),handler是预先定义好的函数
    • pthread_create():创建线程函数
    • pthread_exit():终止线程
    • pthread_attr_init():初始化结构体
    • pthread_attr_destroy():删除
    • pthread_attr_setdetachstate()、pthread_attr_getdetachstate():设置、获取线程的分离状态
    • pthread_attr_setinheritsched()、pthread_attr_getinheritsched():设置、获取线程的继承性

4. 避免产生僵尸进程

  • 父进程可通过调用wait()或waitpid()等函数来等待子进程结束,从而避免产生僵尸进程,但这会导致父进程被挂起(即父进程被阻塞,处于等待状态)
  • 调用signal()函数为SIGCHLD信号安装handler来避免产生僵尸进程
  • 调用signal(SIGCHLD, SIG_IGN)函数来通知内核在子进程结束后将会被内核自动回收

第五章(个人认为考点不多,后面没有整理)

1. 三种互斥锁

  • 快速互斥锁是指调用线程会阻塞直至拥有互斥锁的线程解锁为止
  • 递归互斥锁能够成功地返回并且增加调用线程在互斥上加锁的次数
  • 检错互斥锁则为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误信息

2. 互斥锁的操作步骤

  • 定义互斥锁变量:pthread_mutex_t
  • 定义互斥锁属性变量:pthread_mutexattr_t
  • 初始化互斥锁属性变量:pthread_mutexattr_init();
  • 设置互斥锁属性:pthread_mutexattr_settype、pthread_mutexattr_setpshared、pthread_mutexattr_gettype、pthread_mutexattr_getpshared、pthread_mutexattr_destroy;
  • 初始化互斥锁变量:pthread_mutex_init();
  • 互斥锁上锁:pthread_mutex_lock();
  • 互斥锁判断上锁:pthread_mutex_trylock();
  • 互斥锁解锁:pthread_mutex_unlock();
  • 消除互斥锁:pthread_mutex_destroy()

第六章

  1. 各种函数

总结

核心依然是一、二、三章;其中套接字部分最好将函数与参数一起记住;与此同时掌握循环套接字的流程以及程序编写。对于后面的部分,个人认为大题概率不大(基本没有),记一些重要的函数即可,其余函数见名知意。

posted on 2020-12-09 16:46  千丶颜  阅读(166)  评论(0编辑  收藏  举报