2.在服务器端创建套接字后,会依次调用listen函数和accept函数。请比较并说明两者作用。
listen:将套接字转为可接受连接方式。
accept:受理连接请求,并且在没有连接请求的情况调用该函数,不会返回。直到有连接请求为止。二者存在逻辑上的先后关系。
5.Linux中的文件描述符与Windows的句柄实际上非常类似。请以套接字为对象说明他们的含义。
都是为了区分指定文件而赋予的整数值。
5.何种类型的套接字不存在数据边界?这类套接字接收数据时需要注意什么?
连接指向型TCP套接字不存在数据边界。因此输入输出函数的响应次数不具有意义。重要的不是函数的响应次数,而是数据的收发量。 因此,必须将传输数据的量和接收数据的量制作成编码,保证发送数据的量和接收数据的量是一致的,特别要注意是制作依赖函数响应次数判断代码。
6.修改代码
write(clnt_sock, message, 4);
write(clnt_sock, message+4, 4);
write(clnt_sock, message+8, 4);
write(clnt_sock, message+12, sizeof(message)-12);
先有sockaddr_in结构体,然后转换为sockaddr结构体,传递给bind即可。
小端序:高位字节存放到高位地址。
网络字节序=大端序
除了向sockaddr_in结构体中填充数据要转换成网络字节序,其他情况是自动转换的,不需要程序员考虑。
几种提供的方便的函数:课本中。。
服务器:bind
客户端:connect
6.什么是知名端口?其范围是多少?知名端口中具有代表性的HTTP合同FTP端口号各是多少?
“知名端口(Well-known PROT)”是指预定分配给特定操作的端口。其范围是0~1023,其中最知名的端口是HTTP:80端口和TCP:21
7.题目大概意思是:为什么bind中第二个参数是sockaddr,但是传入的是sockaddr_in
bind函数第二个参数类型是sockaddr结构体,很难份分配IP地址和端口号,因此IP地址和PORT号的分配是通过sockaddr_in完成的。因为该结构体和sockaddr结构体的组成字节序和大小完全相同,所以可以强转。
10.回送地址表示计算机本身,为127.0.0.1
两个:sock,addr结构体
客户端自动在connect函数实现时给套接字分配ip和端口号,无需调用bind函数。
connect函数(客)和accept函数(服)不一定谁先调用,不管怎样,两个都运行了,才能传数据。
数据太大,客户端可能尚未收到(write)全部数据包就调用了read函数
5.什么时候创建连接请求等待队列?它有何作用?与accept有什么关系
listen函数的调用创建了请求等待队列。它是存储客户端连接请求信息的空间。accept函数调用后,将从本地存储的连接请求信息取出,与客户端建立连接。
7.题目回家写一下
回声服务器端无事,回声客户端不妥,write函数马上接read函数,是否能完全接到所有数据,是否需要等待。
解决:提前知悉接收长度,循环read。降低异常使用判断条件,此处划线课本
P85 此处有作业
read和write都有缓冲,函数调用一瞬间是向缓冲输入或者读取数据。
write在数据移到缓冲时返回,当然了,tcp会保证后续传输,这个不必担心。
SYN是同步消息(用来同步的消息)
断开:各发一次fin,四次握手。
此处有5.6道题 请写一下
流控制是UDP和TCP区别的重要标志。
TCP:向10个客户提供服务,服务器需要:1个守门的套接字,和10个套接字对应客户。
UDP:来去多少人,都一个套接字,客户服务器都是。
udp,tcp服务器端都是用bind来绑定ip地址和端口号,bind不分tcp,udp。tcp客户端用connect绑定,udp客户端的sendto()第一次用也会自动分配,所以大家都有方法。
udp有数据边界,所以它的一个数据包能称为数据报。
这里也有题目
与同一主机长时间通话,可将套接字转为已连接,提高效率。
使用connect即可,然后就变成已连接套接字了,还可以使用read、write来替换sendto等。
半关闭,能有效解决close的问题,就是最后一点数据收不到的问题。输入流和输出流,可以关一个,不用两个都关。
1.解释TCP中“流”的概念。UDP中能否形成流?请说明原因
udp不形成流,因为udp不相互连接。
域名和IP转换的学习是因为,客户知道网址发送信息后,需我们转换成ip和端口号才能接收到包。
套接字可选项能查看修改套接字里面的信息。
设置缓冲大小不一定会按照我们输入的完全一样,因为tcp有自己的考量,会向那边接近。
先发fin的才有time_wait,time_wait会使服务器锁定此套接字,如果服务器有其他事情,就会被稍作耽搁,所以可以修改此标题为true,就可以再time wait的情况下分配此套接字。
等待ack来了,才发送第二个数据包。
大文件传输反而禁用nagle会更好,因为文件输出到缓冲不需要多少时间,连续传输能提高速度。
设置nodelay参数为1能禁用nagle。
…消失
5.select函数使用的fd_set结构体在Windows和Linux中具有不同的声明。请说明却别,同时解释存在区别的必然性
Linux的文件描述符从0开始递增,因此可以找出当前文件描述符数量和最后生成的文件描述符之间的关系。但Windows的套接字句柄并非从0开始,并且句柄的整数值之间并无规律可循,因此需要直接保存句柄的数组和记录句柄数的变量
监视内容发生变化时只通知发生变化的事项。
epoll_wait对标select函数。
有一个很大的结构体数组epoll_event,来放发生变化的信息。
条件触发:只要输入缓冲有数据就会一直触发。
边缘触发:只在第一次输入缓冲收到数据时触发,其后即使里面还留有数据也不再触发。
epoll默认条件触发,可以设置边缘触发。
边缘触发两个重点:errno变量保存错误原因、设置为非阻塞I/O。
errno变量保存错误原因:如果缓冲全部读完,可以进行提醒。
设置为非阻塞I/O:非阻塞设置了两个地方,不知道是为什么???
第57行改过试了一下,还可以。
条件触发和边缘触发的区别在于:边缘触发可以分离接收数据和处理数据的时间点。
线程是进程里的单位,共享的是堆区和数据区,独立的是栈区。
线程结束后,进程才结束,有专门函数pthread_join。非线程安全函数都有对应的线程安全函数,临界区的代码可以避免。
线程之间要防止临界区的问题要做到同步。
互斥量:
就是线程用的锁,先创建互斥量,再进行锁和解锁的操作。用的函数有pthread_mutex_lock等。
信号量:
又称二进制信号量,就是在0,1之间跳变,资源是0就要等到,是1,就可以获取,并在用时跳成0,用完后,跳成1。
在控制执行顺序上,也可以用到信号量。
线程的销毁:
线程需要销毁,要么用join要么用detach。