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

posted @ 2022-06-13 22:06  梦想与爱  阅读(284)  评论(0编辑  收藏  举报