• netfinal


    一、填空题

    1. 常用函数

    • int socket(int domain, int type, int protocol)

      • 作用:创建套接字
      • 成功:返回描述符 失败:-1
      • **domain:协议族 **
      • type: socket类型
      • protocol:哪种协议,由于指定了type,这里一般用“0”
    • int close(int fd)

      • 作用:关闭套接字
      • 成功返回0,失败:-1
      • fd:套接字描述符
    • int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen)

      • 作用:服务器绑定地址信息
      • 成功返回0,失败:-1
      • sockfd:套接字
      • myaddr:指向地址结构的指针
      • addrlen:指定结构体变量的大小
    • in_addr_t inet_addr 成功 32位数 失败INADDR_NONE

      • 作用:是将一个ip地址字符串转换成一个整数值
    • int gethostname(char *name, size_t len)

      • 作用:返回本地主机的标准主机名
      • 成功返回0,失败返回-1
    • int inet_aton(const char *ipstring,struct in_addr *inp)

      • 成功返回1,失败返回0
      • 将x.x.x.x形式的IP地址串转换为in_addr类型的结构体
    • in_addr_t inet_addr(const char *ipstring)

      • 成功返回32位整数,失败返回INADDR_NONE
      • 将x.x.x.x形式的IP地址串转换为32位,网络字节顺序的整数
    • ssize_t sendto(int sockfd, const void *buf, // 发送数据的起始地址 size_t len, // 要发送的字节数 int flags, // 无特殊要求为0 struct sockaddr *dest_addr, //接收方地址描述结构体的地址 sockaddr_in socklen_t addrlen // dest结构体的长度 sizeof()表示 ) 成功返回字节数,失败返回-1

    • ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, //发送方地址描述结构体的地址 IPv4 sockaddr_in socklen_t *addrlen //src结构体的长度, ,返回src_addr结构体的字节数 ) 成功返回字节数,失败返回-1

    • int listen( int sockfd, //监听套接字 int backlog // 待处理,连接请求 被accept()处理,backlog不再影响(让监听套接字进入监听状态),成功0失败-1

    • int accept( int sockfd, struct sockaddr *addr, socklen_t *addrlen)

      监听套接字,套接字来自那个地址,地址的结构体占用多少字节(接收客户端连接请求。)

      返回的套接字是响应套接字,用于真正的数据通信

    • int connect(int sockfd, struct sockaddr *serv_addr, socklen_t addrlen)连接服务端 成功0,失败-1

    • ssize_t send(int sockfd, const void *buf, size_t len, int flags)发送数据 成功返回发送的字节数。

    • ssize_t recv(int sockfd, void *buf, size_t len, int flags) 成功返回接收的字节数。返回如果为0,对方关闭了数据发送通道(即半关闭)

    • image-20220519090446091

      notoa:功能是将网络地址转换成“.”点隔的字符串格式。

      ntohs:作用是将一个16位数由网络字节顺序转换为主机字节顺序。

    image-20220517104455214

    2. 常用头文件

    #include <stdio.h>//标准输入输出头文件

    #include <stdlib.h>//定义杂项函数及内存分配函数

    #include <string.h>//字符串处理函数的头文件

    #include <malloc.h>//分配 size 字节的存储区

    #include <errno.h>// ISO C99标准错误代码

    include <math.h>//定义数学函数

    #include <dirent.h>//用于目录操作的头文件

    #include <unistd.h>//标准符号常量和类型

    #include <time.h>//定义关于时间的函数

    #include <sys/types.h>//数据类型的声明

    include <sys/socket.h> 主文件

    include <arpa/inet.h>Internet地址转换

    netinet/in.h - Internet地址

    sys/select.h - select I/O模型

    sys/epoll.h - epoll I/O模型

    netdb.h - 网络数据库相关,例如域名解析

    fcntl.h - 文件控制

    3.多线程

    1. 头文件

      #include<pthread.h>

    2. 常用函数

      1. int pthread_create(pthread_t *restrict tid, const pthread_attr_t *restrict attr, void (start_routine)(void *), void *restrict arg)
      2. int pthread_join(pthread_t tid, void **status)指定线程结束 需要用线程的执行结果
      3. int pthread_detach(pthread_t tid)不需要执行结果,释放,不等待结束
      4. void pthread_exit(void *retval)终止调用线程

    线程同步

    Mutex互斥量,当两个线程竞争使用资源时,为避免执行顺序引起的错误

    1. Int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) //互斥量的线程启动前调用

      若无特殊要求,第二个参数设置为null

    2. int pthread_mutex_lock(pthread_mutex_t *mutex)

      进入互斥量临界区

    3. int pthread_mutex_unlock(pthread_mutex_t *mutex)

      退出临界区

    4. int pthread_mutex_destory(pthread_mutex_t *mutex)

      当互斥线程全部结束时调用


    信号量

    1. int sem_init(sem_t *sem,int pshared,unsigned int value)

      若信号量只供进程内线程调用,Pshared设置为0,参数value>=1,表示可用资源数量

    2. int sem_wait(sem_t *sem) 进入临界区调用 (p()阻塞)

    3. int sem_post(sem_t *sem) 退出临界区调用 (v()执行)

    4. int sem_destory(sem_t *sem) 不再需要时释放


    main() 进程的默认执行体、主线程 return结束后, 进程会结束,其他所有依赖线程终止。 pthread_exit()结束,主线程会结束,但其它线程的执行不受影响

    4. 常用端口

    TCP 80 http 53 dns 25 smtp 20/21 ftp 23 telnet 110 pop UDP 53 dns

    69 tftp 161 snmp 22ssh

    0:不作用或者作为特殊的用途

    1~255:保留给特定的服务

    256~1023:保留给其他服务

    1024~4999:用作任意客户的端口

    5000~65535:用作用户服务器端口

    5. 常用命令

    Ipconfig:查看网络接口信息

    Ifconfig:查看所有网络接口信息

    Ping:验证网络是否连通

    Traceroute:路由追踪

    Nslookup:域名解析

    Route:查看linux服务器上的路由表

    Netstat:查看端口的连接状态

    netstat -anu4 可查看udp的ipv4下他的监听端口号(会显示ip地址 端口号)

    chmod 7 udpc 设置权限

    编译:gcc - o udpc1 udplc01.c(要生成的文件,源文件)

    TCPDump: 对网络中传送的数据包完全截获下来提供分析

    Wireshark:截取网络封包,显示出最为详细的网络封包资料

    Nmap:网络连接端扫描软件,用来扫描网上电脑开放的网络连接端。确定哪些服务运行在哪些连接端,并且推断计算机运行哪个操作系统

    Iptables: IP 信息包过滤系统,控制 IP 信息包过滤和防火墙配置

    6.填空题

    1、下列选项中,将端口号由本机字节顺序转换为网络字节顺序的函数()。

    htonl****()或htons()

    3、RFC中,HTTP服务采用的默认端口号是()。80

    4、某些函数在单线程中执行时可以获得正确结果,但在多线程并发执行时出现了逻辑错误,原因是(可能发生死锁,线程不安全,内存泄漏等问题)。

    5、在 Linux编程中,要使用 POSIX标准的线程库,需要包含哪一个头文件?(pthread.h)

    6.在流式套接字上调用recv(),若返回值为0,表示(对方关闭了数据通道)。

    7.Windows API 中,SendMessageO的作用是(发送消息)。

    8.在 WinSock2编程时,除默认的库外,需要编译器单独加载的库是(ws2_32.lib)

    9.让套接字进入监听状态的函数是()。listen(int sockfd,int backlog)

    10.Linux中,使用信号量进行线程同步时,相当于操作系统中Р操作的函数调用是()。.

    int sem_wait(sem_t *sem)

    11.Linux中,线程A创建了线程B后,需要等待线程B执行完成后A再继续执行,则应在A中调用的线程控制函数是()。

    int pthread_join(pthread_t tid,void **status)

    12.函数inet addrO的作用是()

    将x.x.x.x形式的IP地址串转换为32位、网络字节顺序的整数

    13.套接字s工作在阻塞模式,在其上调用哪个函数时不会阻塞?(bind)

    recv accept connect bind 都会阻塞

    15、gethostbynameO的作用是( )。获取主机信息

    二、简答题

    1. 网间进程通信需要解决的根本问题有哪些?需要注意哪些细节的处理?

      1)网间进程的标识问题;

      (2)如何与网络协议栈连接的问题;

      (3)协议的识别问题;

      (4)不同的通信服务的问题.

      1)字节顺序:Internet采用Big Endian

      2)字的长度

      3)字节定界:UDP有界,TCP无界

      4)字符编码(尤其是Java/Python等高级语言,网站开发中同样涉及)

      5)日期、时间、等国际化和本地化处理(网站开发中同样涉及)

    2. 在 Linux的TCP并发服务端中,只关注是否有连接请求或数据到达,请用文字描述select模型的编程步骤,注明相应的函数和宏.…

      FD_ZERO(…)

      FD_SET(…) //将监听套接字存入读集合

      while(…)

      {

      准备集合(循环)

      设置timeout

      select(…)

      循环:若成功,逐一判断某套接字是否仍在某集合中,若是,执行相应的I/O操作或出错处理

      }

    3. 什么是线程,什么是进程?

      进程:

      • 程序的运行实例,是软件的动态体现,侧重代码执行过程的管理和控制,通过运行执行预期功能

      • 一个进程实体由程序代码、数据和进程控制块三部分构成。

      线程:

      • 描述代码的微观运行情况,是cpu调度的基本单位,线程依附于进程
      • 线程自己不拥有系统资源,但它可与同一进程的其 它线程共享进程所拥有的全部资源
    4. 先执行左下角的客户端,发现第二个客户端根本没有执行,

      提示连接被对端复位,为什么?(10分主观题)

      1.1)tcpls01v2,可以正常运行,尽管可以启动多个客户端,但仍然只有一个客户端执行完全部计算。其它的客户端根本没有机会参与计算,为什么?

    5. 给客户端分配id的原因是什么?

    6. 实际应用中面临的复杂问题

      假设套接字接收到的字节数是len,但应用程序读取的字节数是part,part <len,并且下次接收以前只处理了part/2个字节,后面该如何接收?前面的处理都比较简单、理想化,实际是比较复杂的。

      假如应用缓冲区中接收到了50个字节,还有50个字节在系统缓冲区中还没有读,并且这次接收的50个字节只处理了25个字节,此时,应用缓冲区还有25个字节没有处理,后面再接收的那些数据放到缓冲区的什么位置,才能保证

      1. 前面没处理的字节不要丢失,不要被覆盖
      2. 整个缓冲区要有足够的空间来容纳我新读入的数据,需要去凑,因为流式套接字数据不分界

    三。判断题

    1. epoll模型中,最多可以同时管理64个套接字 ×

    2. Linux下,大部分套接字函数的返回值为-1时,表示操作失败。 √

    3. 在Linux 中,服务端要使用1024以下的端口,需要具备root权限。 √

    4. WinSock中的select模型用法与Linux中的完全相同。 ×

    5. 在 Linux中,若监听套接字工作在非阻塞模式,accept(返回的响应套接字也会自动工作在非阻塞模式, √

    6. TCP通信中,一方调用send的次数和另一方调用recv的次数可以不同。

    7. ·发送4字节整数前,应将其转换为接收方硬件系统采用的字节顺序。

    8. 不同OS中,协议栈的实现形式不同,有的是在内核中,有的不是

    9. Windows 下,WSAStartup()的作用是初始化 WinSock的执行环境。 √

    10. wSAGetLastErrorO在任何情况下都可以获取上次套接字操作过程中

    的错误代码。 ×

    image-20220613215509401

    image-20220613215516675

    四、编程题

    29、设计并实现一个基于Linux的TCP服务端,只有一个main函数,并发特性,工作IP地址是0.0.0.0,端口号是2022,所有套接字工作在非阻塞模式。不使用多线程。进入监听状态后,开始无限主循环:

    1)准备工作。

    2)无限主循环

    2.1)等待客户端连接请求

    2.2)当收到客户端连接请求后,显示格式化字符串“Connection %d from %s:%d”,其中第1个%d为服务端启动后连接的客户端的从1开始的序号,每当建立一个连接请求,该序号就增1。%s和第2个%d对应客户端套接字的点分十进制P地址和端口号,

    2.3)与客户端进行交互,循环:

    2.3.1)接收客户端发送过来的文字信息,不显示在屏幕上。客户端发送的数据组成为:2字节短整型数,其值为后面字符的个数,该值可以为0;从第3个字节开始是标准ASCII字符组成的字符串(不含字符串结束符)

    2.3.2)将接收的文字信息中的问号替换为句号,再发送回客户端,反馈格式与接收格式相同

    2.3.3)检测到网络故障后,显示"network error",结束交互

    2.3.4)检测到客户端关闭了连接后,显示"connectionclosed",结束交互

    2.5)关闭响应套接字

    3)在主循环结束后,关闭监听套接字

    要求:监听套接字为s0,响应套接字为s1,其它的变量名自行确定。


    29、设计并实现一个基于Linux的TCP服务端,只有一个main函数,无并发特性,工作IP地址是0.0.0.0,端口号是2021,所有套接字工作在阻塞模式。进入监听状态后,开始无限主循环:

    1)准备工作。

    2)无限主循环

    2.1)等待客户端连接请求

    2.2)当收到客户端连接请求后,显示格式化字符串“Connection %d from %s:%d”,其中%d为服务端启动后连接的客户端的从1开始的序号,每当建立一个连接请求,该序号就增1。%s和第2个%d对应客户端套接字的点分十进制P地址和端口号,

    2.3)与客户端进行交互,循环:

    2.3.1)接收客户端发送过来的文字信息,不显示在屏幕上。客户端发送的数据组成为:2字节短整型数,其值为后面字符的个数,该值可以为0;从第3个字节开始是标准ASCII字符组成的字符串(不含字符串结束符)

    2.3.2)将接收的文字信息中的问号替换为句号,再发送回客户端,反馈格式与接收格式相同

    2.3.3)检测到网络故障后,显示"network error",结束交互

    2.3.4)检测到客户端关闭了连接后,显示"connectionclosed",结束交互

    2.5)关闭响应套接字

    3)在主循环结束后,关闭监听套接字

    要求:监听套接字为s0,响应套接字为s1,其它的变量名自行确定。

    五、select模型

    1. 套接字存储在fd_set集合,select模型会监控一段时间内集合中所有有效的套接字是否“操作就绪”,

      1. 若是会保留下来
      2. 否则将该套接字移出集合
    2. int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds,struct timeval *timeout)

      1. nfds : 三个集合中所包含的最大描述符值+1

      2. readfds : 检查套接字可读性(响应套接字有数据到达,调用recv;对于监听套接字,有连接请求到达,可以调用accpet)

      3. writefds :检查可写性 仅对响应套接字有效,成功调用 send()

      4. exceptfds:异常套接字集合,设NULL会无限期等待至出错

      5. timeout:超时时间设置,其类型是:

        struct timeval {

          long tv_sec; //seconds

          long tv_usec; //microseconds

        };//***timeout两个成员均为0,则select()会立即返回 ***

      6. 返回值

        1. -1:错误,
        2. 0:规定时间内所有集合中的描述符都未变为就绪状态,
        3. >0:三个集合中处于就绪状态的描述符总数
    3. select模型宏操作

      1. FD_ZERO(fd_set *) 清空某个几个,仅进行一次

      2. FD_SET(int, fd_set*)将某个描述符加入指定的集合

      3. FD_ISSET(int, fd_set*) 调用select模型后,判断某套接字是否存在于集合中,若存在,则可以对其进行某种I/O或出错处理

      4. FD_CLR(int, fd_set*) 将某个描述符从集合中移出,即不再关注该描述符

        使用select模型的框架

    4. select模型使用

      FD_ZERO(...)//把set队列初始化成空队列

      FD_SET(...) //将监套接字加入读集合

      while(...)
      {

      准备集合(循环)

      设置timeout

      select(...)

      循环:若成功,逐一判断某套接字是否存在某集合中,

      若失败,执行相应的I/O操作或出错处理

      }

    六、阻塞模式、非阻塞模式

    1. 阻塞模式

      1. 当调用某函数时,若操作条件不具备,函数会一直处于等待状态,程序的执行进程会在该函数调用处停顿,知道操作完成或发生错误为止
      2. recv() accept()connect() bind()
      3. 典型的阻塞操作
        1. accept:当没有新的连接请求到来时,会一直等待,直到新的连接请求到来或发现错误
        2. recv/recvfrom:当没有数据到达时,会一直等待,直到数据到达或出现错误
        3. 操作不具备一直等待
    2. 非阻塞模式

      1. 当调用某个函数时,无论操作条件是否具备,函数均会立即返回,程序的执行进程不会在该函数调用出停顿,而是继续执行。

      2. 通过返回值及errno判断函数返回的原因

        1. 返回值大于0,表示读取到了数据

        2. 返回值为-1,errno为EWOULDBLOCK表示操作条件不具备,表示无数据到达

          其他:errno表示出现了错误

      3. accept:当没有新的连接请求到来时,会一直等待

      4. recv:当没有数据到达时,会一直等待

      5. 非阻塞模式编程

        1. socket(AF_INET,SOCK_STREAM|SOCK_NONBLOCK,0)
        2. fcntl(sock,F_SETFL,fcntl(sock,F_GETFL,0)|O_NONBLOCK);
      6. 非阻塞模式编程框架

        n = recv(...)

        if(n>0)

        此时,数据已经读入到应用缓冲区,进行相应处理

        else if(n == 0)

        此时对方关闭了连接

        else

        if(errno == EAGAIN || errno == EWOULDBLOCK)

        并非真正错误,而是无数据到达

    七、UDP/TCP编程框架

    1. UDP编程框架

      服务器

      1)创建数据报套接字

      2)绑定(地址和端口信息,端口需要通知所有客户端)

      3)等待接收客户端数据

      4)收到数据后,按照通信规程(也可称为业务逻辑)处理,一般要反馈

      5)在必要的情况下,关闭套接字

    ​ 客户端工作过程 :

    ​ 1)创建数据报套接字

    ​ 2)根据服务端公布的地址、端口信息,向服务端发送数据

    ​ 3)发送数据或反馈信息时,按与对方约定好的通信规程处理

    ​ 4)结束后,关闭套接字

    1. 流式套接字编程框架

      客户端

      1)创建流式套接字

      2)根据服务端公布的地址信息,连接到服务端

      3)连接成功后,可以按照通信规程(业务逻辑)传输数据

      ​ 3.1)发送数据:将数据从应用程序缓冲区复制到套接字的发送缓冲区,至于何时真正发送到对方,由协议栈决定

      ​ 3.2)接收数据:将数据从套接字的接收缓冲区移动到应用程序的缓冲区,

      4)数据传输完成后,可关闭套接

      服务端

      1)创建流式套接字,目的是监听连接请求

      2)绑定对外公布的地址信息

      3)确定连接请求队列大小,进入监听套接字监听状态

      4)当有客户端的连接请求到来时,创建一个为该客户端提供1对1服务的流式套接字,它只起数据传输作用,称为响应套接字

      5)响应套接字与客户端套接字成为通信双方,这个通信是有连接的,在此基础上,可以按照通信规程(业务逻辑)传输数据

      ​ 5.1)发送数据:将数据从应用程序缓冲区复制到套接字的发送缓冲区,至于何时真正发送到对方,由协议栈决定

      ​ 5.2)接收数据:将数据从套接字的接收缓冲区移动到应用程序的缓冲区,

      6)数据传输完成后,可关闭响应套接字

      7)一般情况下,不关闭监听套接字,除非有特殊要求

    image-20220522080041225

  • 相关阅读:
    HRBUST 1819 石子合并问题--圆形版
    Linux 用户信息英文解释
    day 09 Linux下常见的打包压缩命令
    day 09作业
    第8天作业
    day 08 重定向/管道/sort/uniq/awk详解
    什么是输出重定向
    day07 Linux文件类型及软链接
    第6,7天作业
    day06 Linux根目录下重要目录
  • 原文地址:https://www.cnblogs.com/dreamzone/p/16372510.html
Copyright © 2020-2023  润新知