WSAStartup 成功之后应该是将 wsaData 的结构体中的字段进行赋值了,因为传入的是它的指针。
WSAStartup 应该是进行准备 socket 环境的工作
SOCKET socket (int af, int type, int protocol); 中 af 的地址簇是什么意思
ipv4 等
https://blog.csdn.net/m0_38062470/article/details/110680118
https://blog.csdn.net/linglongbayinhe/article/details/83214171
https://blog.csdn.net/jeffasd/article/details/51461568
在 listen 的 backlog 的描述中,服务器是不支持并发的么
listen 因为 backlog 而不能连接的时候,算是执行失败么
在 accept 函数的第二个参数 addr 开始指向的是空结构体,连接成功才会将结构体的字段赋值
connect 的第一个参数 s 是发送连接请求的,还是接收连接请求的
为什么设计到目标地址结构体时要加上结构体的长度呢?
typedef _W64 unsigned int UINT_PTR, *PUINT_PTR; | |
typedef UINT_PTR SOCKET; |
https://blog.csdn.net/Fuel_Ming/article/details/122931926
文件描述符
https://zhuanlan.zhihu.com/p/143847169
https://baike.baidu.com/item/ 文件描述符 / 9809582
https://blog.csdn.net/yuhan61659/article/details/81746043
将 socket 设置非阻塞模式的时机,在创建 socket 的时候它有默认的模式么?
默认是阻塞模式
socket 就是文件描述符(SOCKET),
参考作品:https://github.com/UncleBloom/httpServer
文件描述符应该是标识一个文件缓冲区,
select 的作用是什么?
是怎么监听到客户端发来信息的?
在哪里检测到客户端来连接的
如果 select 用来检测文件描述符指向的文件是否发生变化的话,那么为什么在客户端没有连接的时候,select 是阻塞的,客户端连接之后,就不阻塞了
上面的发生变化是指只要客户端连接进行,还是需要客户端发送来消息呢?
select 的参数中
int maxfdp 是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加 1,不能错!在 Windows 中这个参数值无所谓,可以设置不正确。
若将 NULL 以形参传入,即不传入时间结构,就是将 select 置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止
select 设置的 write 和 read 之间会发生通信、数据传递么?
select 的作用是通过文件标识符来监视文件的变化的,write 和 read 是不同的文件类型,可能设置监视的方式不同,因此要分开,这和它们的通信、数据传递无关。
“每次循环都要清空,否则不能检测描述符变化” 这是为什么?
如果在 select 的地方阻塞了,那么,客户端发送请求的时候,又该怎么运行代码来改变文件标识符指向的文件呢?
是 listen 起的作用还是 bind 起的作用,listen 起的作用,bind 是将 socket 和地址进行了绑定,listen 是开启监听,之后才能接受请求。
应该是,当 select 的返回值是 0 的时候,就会发生阻塞
有了 FD_SET(srvSocket, &rfds);
,那么当 srvSocket 接受到请求的时候,它就会发生变化。
ioctlsocket(srvSocket, FIONBIO, &blockMode)
将 socket 设置为非阻塞模式是在哪个地方起作用的呢?
https://blog.csdn.net/yuhan61659/article/details/81746043
select 是会修改传入的 fd_set 的 read 和 write 指针的,根据
这里面
的解释,应该是清除不满足条件的了,
那如何判断是否满足条件呢?sessionSocket 始终不满足读的条件,srvSocket 在接受了请求之后就不再满足读的条件了。
百度百科
select 的选择性: https://blog.csdn.net/xhu_eternalcc/article/details/24439453
但是,select 判断文件描述符指向的文件是否有事件发生,这个事件得在什么时候发生才能被 select 选中呢?
依据刚建立连接时候的情形,select 应该是阻塞的,一直在等待连接,
那是否是,select 只能选择一个呢?即只要有一个发生变化了,select 就会返回了。
select 可以设置阻塞,也可以设置非阻塞,在这里由于最后一个参数设置为 null,所以是阻塞的。
当已经建立连接,但是客户端没有发送消息,为什么 sessionSocket 能够一直留在 wfds 中呢?
难道是因为,可写的就是会一直存留
新创建一个 SOCKET,然后加入试试。貌似是对的,当在 select 前 sessionSocket = 2; FD_SET(sessionSocket, &wfds);
时,这时没有开启客户端,select 就不再阻塞了。随便设置的会出现 ioctlsocket() failed with error!
的错误。
struct sockaddr_in { | |
short sin_family; | |
u_short sin_port; | |
struct in_addr sin_addr; | |
char sin_zero[8]; | |
}; | |
struct in_addr { | |
union { | |
struct { u_char s_b1, s_b2, s_b3, s_b4; } S_un_b; | |
struct { u_short s_w1, s_w2; } S_un_w; | |
u_long S_addr; | |
} S_un; | |
}; |
代码跑起来了,现在去根据他的代码内部的数据处理,得到正确的输入输出,
输入的都是字符串,思考代码内部的转换过程。
当前代码好像还没有 WSAStartup
输入的 ip 地址为点分十进制,
我们输入的 ip 应该是本机的 ip 吧,不能是任选的;
127.0.0.1
在 main 函数中配置服务器的时候就配置 filepath 了么?
这不是请求的文件,而是文件夹的路径。
http://127.0.0.1:5050
ip.src ==127.0.0.1 && tcp.port == 5050
ip.addr ==127.0.0.1
目前的问题,在重新配置网络之后,浏览器发出的网络请求仍然是针对旧端口和 ip 的,
看 main 函数捋清楚执行过程查找使用当前服务器使用的 ip 和端口号,在重新读取文件后重置他们的值
# 模块二
RdtReceiver 中的 receive (Packet) 要进行数据的检验
# 实验二
“编码报文序号的二进制位数” 是什么,
超时 TimeoutHandler 是由网络环境调用的么
计时器是放在网络环境中的,因此也是网络环境调用 TimeoutHandler
上面是不是错误了,当传输了多个数分组了,每当一个分组传输成功后不是重启定时器的么
StopWait、GBN、简化版的 TCP 协议只需要一个定时器
在 Packet 中的序号和确认号
是和该定时器相关的 Packet 序号 是什么意思
即使是 GBN 和简化版 TCP 这些协议,也要设置该参数(应为最早发出但未确认的 Packet 序号)
根据上面这句话,Packet 的序号是否是连续的
先配置环境,主要是 stdafx.h 中的库路径
在头文件中 GBNReceiver.h 、 GBNSender.h、SRReceiver.h、SRSender.h、TCPReceiver.h、TCPSender.h。
响应的,有 GBNReceiver.cpp 、 GBNSender.cpp 、 SRReceiver.cpp 、 SRSender.cpp 、 TCPReceiver.cpp 、 TCPSender.cpp
序号和确认号是怎么发挥作用的
# GBN
expectSequenceNumberSend 为当前使用的序号,同时对应 packetWaitingAck 数组中的下标
在一开始的时候 expectSequenceNumberRcvd 怎么设置,如果发送方是从 0 开始发送的话,那么 expectSequenceNumberRcvd 应该设置为 0
这里有重发分组,如果是第一个分组就出错了呢?
报文和分组有区别的么
# GBNSender
发送方接收到一个 ack 分组之后就关闭定时器,如果还存在已发送但没接受到 ack 的分组,就重启定时器。
# GBNReceiver
在 GBNReceiver 中,
在 GBNReceiver 中仅设置了一个 lastAckPkt 来保存上次发送确认的报文?
由 GBNReceiver 发送的分组 Packet 没有用到 seqnum 字段,只用到了 acknum 字段,且 acknum 等于正确接受到的分组的 seqnum
expectSequenceNumberRcvd 是递增的,意味着只能按顺序接受分组,没有按序接受时,则发送上次确认的分组
# SR
# SRSender
窗口长度为 N=4
expectSequenceNumberSend
sureNum 和 packetWaitingAck 的数组长度是一致的,且主要用 expectSequenceNumberSend 索引
sureNum 在某序号处为 0 时,表示该分组已分送但未确认,发送且确认则置为 1
# SRReceiver
窗口长度为 M=4
loadPkt 用来缓存的报文 ? 它的长度设置为 8 ?如果考虑窗口的大小为 4,那长度为 4 是不是就行了?
在 loadPkt 的确认号 acknum 也等于接收到的分组的序号 seqnum
无论是窗口内的还是窗口外的分组被接收后都要给出回复的 ACK,这个 ack 就是接受到的分组的序列号
rcv_base 是缓存数组中窗口的开始下标,但是它指向的分组不一定是已被缓存的,即 acknum=-1
# TCP
快速重传:https://blog.csdn.net/whgtheone/article/details/80983882
加入发送方收到
# TCPReceiver
发送的 ack 分组的 ack 序号就是接受的分组的 seqnum 序号
发送方的 base 和接收方的 rcv_base 是相同的么?
某一时刻不相同,但目的是为了使相同。
是的,当序号较大分组首先到达接收方时,rcv_base 是不更新的。当接受方窗口内的分组从窗口开始位置有连续到达时,rcv_base 更新,发送的 ack 传到发送方,使它的 base 更新到和 rcv_base 相同。
# 实验三
PDU: https://blog.csdn.net/qq_39806533/article/details/81877588
https://blog.csdn.net/weixin_39856589/article/details/110993720#:~:text = 不同的网段之间的,好多人想不到:)
交换机,路由器上的 S 口 F 口 E 口 G 口 是什么? https://blog.csdn.net/immenselee/article/details/80401059
子网划分
每个 200,8 位
宿舍 1: 211.69.4.0/24
宿舍 2: 211.69.5.0/24
宿舍 3: 211.69.6.0/24
每个 20,5 位
学院 1: 211.69.7.128/27
学院 2: 211.69.7.160/27
学院 3: 211.69.7.192/27
学院 4: 211.69.7.224/27
图书馆 100 7 位
211.69.7.0/25