Fork me on GitHub

网络编程练习这些就ok

1,什么是C/S架构?

1
2
3
4
5
6
7
8
9
    C指的是client(客户端软件),S指的是Server(服务端软件)
    一个C/S架构就是,实现服务端软件与客户端软件基于网络通信。
 
互联网中处处是C/S架构
      如12306网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种)
      腾讯作为服务端为你提供视频,你得下个腾讯视频客户端才能看它的视频)
 
C/S架构与socket的关系:
        我们学习socket就是为了完成C/S架构的开发

  

2,互联网协议是什么?分别介绍五层协议中每一层的功能?

  

1
2
3
4
5
简单说,计算机之间的通信标准,就称为互联网协议<br>
按照功能不同,人们将互联网协议分为osi七层或tcp/ip五层或tcp/ip四层<br>
tcp/ip四层:应用层,传输层,网络层,网络接口层<br>
tcp/ip五层:应用层,传输层,网络层,数据链路层,物理层<br>
osi七层:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层

  

3,基于tcp协议通信,为何建立链接需要三次握手,而断开链接却需要四次挥手

  三次握手:client发送请求建立通道;server收到请求并同意,同时也发送请求建通道;client收到请求并同意,建立完成

  四次挥手:client发送请求断开通道;server收到请求并同意,同时还回复client上一条消息;server也发送请求断开通道;client受到消息结束

1
2
3
4
5
6
7
8
9
10
11
12
为什么TCP协议终止链接要四次?
 
1、当主机A确认发送完数据且知道B已经接受完了,想要关闭发送数据口(当然确认信号还是可以发),
就会发FIN给主机B。
 
2、主机B收到A发送的FIN,表示收到了,就会发送ACK回复。
 
3、但这是B可能还在发送数据,没有想要关闭数据口的意思,所以FIN与ACK不是同时发送的,
而是等到B数据发送完了,才会发送FIN给主机A。
 
4、A收到B发来的FIN,知道B的数据也发送完了,回复ACK, A等待2MSL以后,没有收到B传来的
任何消息,知道B已经收到自己的ACK了,A就关闭链接,B也关闭链接了。

  

4,为何基于tcp协议的通信比基于udp协议的通信更可靠?

tcp:可靠 对方给了确认收到信息,才发下一个,如果没收到确认信息就重发
udp:不可靠 一直发数据,不需要对方回应

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1)UDP:user datagram protocol(用户数据报协议)
特点:
——1:面向无连接:传输数据之前源端和目的端不需要建立连接
——2:每个数据报的大小都限制在64k8个字节)以内
——3:面向报文的不可靠协议(即发出去的数据不一定会接收到)
——4:传输速率快,效率高
——5:现实生活实例:邮局寄件,实时在线聊天,视频协议等等
2)TCP:transmission control protocol(传输控制协议)
 特点:
——1:面向连接:传输数据之前需要建立连接
——2:在连接过程中进行大量的数据传输
——3:通过“三次握手”的方式完成连接,是安全可靠的协议
——4:传输效率低,速度慢
  

  

‍5,流式协议指的是什么协议,数据报协议指的是什么协议?

1
2
3
4
5
TCP协议,可靠传输
数据报协议: UDP协议,不可传输
也就是TCP和UDP的区别:
    TCP是面向连接的,可靠的字节流服务
    UDP是面向无连接的数据报服务

  

6,什么是socket?简述基于tcp协议的套接字通信流程流式协议:

1
2
3
4
5
6
7
8
    Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,
Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,
对用户来说,一组简单的接口就是全部。
 
服务端:创建socket对象,绑定ip端口bind(),  设置最大链接数listen(),  accept()与客户端
的connect()创建双向管道, send(), recv(),close()
 
客户端:创建socket对象,connect()与服务端accept()创建双向管道 ,  send(), recv(),close()

  

7,什么是粘包? socket 中造成粘包的原因是什么? 哪些情况会发生粘包现象?

1
2
3
    粘包:数据粘在一起,主要因为:接收方不知道消息之间的界限,不知道一次性提取
多少字节的数据造成的数据量比较小,时间间隔比较短,就合并成了一个包,
这是底层的一个优化算法(Nagle算法)

  

8,基于socket开发一个聊天程序,实现两端互相发送和接收消息

  服务端:

客户端

  

9,基于tcp socket,开发简单的远程命令执行程序,允许用户执行命令,并返回结果

服务端:

客户端

  

10,基于tcp协议编写简单FTP程序,实现上传、下载文件功能,并解决粘包问题

 客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# _*_ coding: utf-8 _*_
 
import socket
import struct
import json
downlaod_dir = r'D:\文件传输\client\download'
 
ip_port = ('127.0.0.1',8808)
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(ip_port)
while True:
    cmd = input(">>>").strip()  #get D:\文件传输\server\a.avi
    if not cmd:continue
    phone.send(cmd.encode('utf-8'))
    #接受文件的内容,以写的方式打开一个新文件,接受服务端发来的文件内容,并写入客户端的新文件
    #第一步,先收报头的长度,然后解包
    obj = phone.recv(1024)
    header_size = struct.unpack('i',obj)[0]
    #第二部 再收报头
    header_bytes = phone.recv(header_size)
 
    #第三部,从报头中解析除对真实数据的描述信息
    header_json = header_bytes.decode('utf-8')
    header_dic = json.loads(header_json)
    '''
     header_dic = {
                'filename':filename,  #a.avi
                'md5':'dsdsd',
                'file_size':os.path.getsize(filename)
            }'''
    print(header_dic)
    total_size = header_dic['file_size']
    filename = header_dic['filename']
 
    #第四步,接受真实的数据
    with open('%s/%s'%(downlaod_dir,filename),'wb') as f:
        recv_size = 0
        # recv_data = b''
        while recv_size <total_size:
            res = phone.recv(1024)
            # recv_data += res
            f.write(res)
            recv_size += len(res)
            print("总大小: %s  \n已经下载大小  :%s"%(total_size,recv_size))
 
    # print(recv_data.decode('utf-8'))
phone.close()

  

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# _*_ coding: utf-8 _*_
import subprocess
import socket
import struct
import json
import os
share_dir =r'/文件传输/server/share'
 
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip_port = ('127.0.0.1',8808)
phone.bind(ip_port)
phone.listen(5)
print("starting....")
while True#链接循环
    conn,client_addr = phone.accept()
    print(client_addr)
    while True: #通信循环
        try:
            #收命令
            res = conn.recv(1024)   #b'get a.txt'
            if not res :continue
            #解析命令,提取相应的参数
            cmds = res.decode('utf-8').split()
            filename = cmds[1]
            #以读的方式打开文件,读取文件内容发送给客户端
            # with open(filename,'rb') as f:
            #     conn.s
              #制定固定长度的报头
            header_dic = {
                'filename':filename,  #a.avi
                'md5':'dsdsd',
                'file_size':os.path.getsize(r"%s/%s"%(share_dir,filename))
            }
            header_json = json.dumps(header_dic)
            header_bytes = header_json.encode('utf-8')
             #先发送报头的长度
            conn.send(struct.pack('i',len(header_bytes)))
             #再发报头
            conn.send(header_bytes)
             #再发真实的数据
            with open('%s/%s'%(share_dir,filename),'rb') as f:
                # conn.send(f.read())
                for line in f:
                    conn.send(line)
 
 
        except ConnectionResetError:
            break
    conn.close()
phone.close()

  

函数版本服务端

  

函数版本客户端

  

面向对象版本服务端

  

面向对象版本客户端

  

11,基于udp协议编写程序,实现功能

 服务端:

  

客户端:

  

UDP不会发生粘包现象,下面举例说明

客户端

  

服务端

  

12,执行指定的命令,让客户端可以查看服务端的时间

 

13,执行指定的命令,让客户端可以与服务的的时间同步

服务端

  

客户端

  

posted @   战争热诚  阅读(1266)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示