python-fullstack-s13-day32-python网络编程

网络编程部分知识点总结

一、软件开发的架构

  1、C/S架构:

    C/S即:client与server,中文的意思是客户端与服务器架构,这种架构也是从用户层面(也可以是物理层面)来划分的。这里的客户端一般泛指客户端应用程序EXE,程序需要先安装后,才能运行在用户的电脑上,对用户的电脑操作系统环境依赖较大。

  2、B/S架构:

    B/S即:browser与server,中文的意思是浏览器端与服务器端架构,这种架构师从用户层面来划分的。Browser浏览器其实也是一种client客户端,只是这个客户端不需要大家去安装什么应用程序,只需在浏览器上通过HTTP请求服务器端相关的资源(网页资源),客户端Browser浏览器就能进行增删改查。

二、网络基础部分

  2.1、基础部分

  1、以太网:局域网与交换机

  2、广播:

    主机之间“一对所有”的通讯模式,网络对其中每一台主机发出的信号都进行无条件复制并转发,所有主机都可以接受到所有的信息,无论你是否需要,由于其不用路径选择,所以其网络成本可以很低廉。有线电视网就是典型的广播型网络,我们的电视机实际上是接收到所有的频道的信号,但只将一个频道的信号还原成画面,在数据网络中也允许广播的存在,但是其被限制在二层交换机的局域网范围内,禁止广播数据穿过路由器,防止广播数据影响大面积的主机。

  3、ip地址与ip协议:

    规定网络地址的协议叫ip协议,它定义的地址称为ip地址,广泛采用的v4版本即ipv4,它规定网络地址由32位二进制表示;其范围为0.0.0.0 - 255.255.255.255;一个ip地址通常写成四段十进制数,例如176.16.10.1。

  4、mac地址:

    ethernet规定接入internet的设备都必须具备网卡,发送端和接收端的地址便是指网卡的地址,即mac地址。mac地址,每块网卡出厂时都有一个全世界唯一的mac地址,长度为48位2进制,通常由12位16进制数表示,前六位是厂商编号,后六位是流水线号。

  5、arp协议:

    地址解析协议,即ARP,address resolution protocol,是根据ip地址获取物理地址的一个TCP/IP协议;主机发送信息时将包含目标ip地址的arp请求广播到网络上的所有主机,并接收返回消息,以此确认目标的物理地址。收到返回消息后将该ip地址和物理地址存入本机arp缓存并保留一定时间,下次请求时直接查询arp缓存,以节省资源。

    地址解析协议是建立在网络中各个主机互相信任的基础上的,网络上的主机可以自主发送arp应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其计入本机arp缓存,由此攻击者就可以向一主机发送伪arp应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个arp欺骗。arp命令可用于查询本机arp缓存中ip地址和mac地址的对应关系,添加或删除静态对应关系等。相关的协议有rarp 代理arp。ndp用于在ipv6中代替地址解析协议arp。

  6、广域网与路由器

   7、路由器:

    路由器,router,是连接因特网中各局域网、广域网的设备,它会根据信道的情况资助选择和设定路由,以最佳的路径,按照前后顺序发送信号,路由器是互联网络的枢纽。目前路由器已经广泛应用于各个行业,各种不同档次的产品已成为实现各种骨干网内部连接、骨干网间互联和骨干网与互联网互联互通业务的主力军。路由和交换机之间的主要区别就是交换机发生在OSI参考模型第二层(数据链路层),而路由发生在第三层,即网络层。这一区别决定了路由和交换机在移动信息过程中需使用不同的控制信息,所以说两者实现各自功能的方式是不同的。

    路由器又称为网关设备gateway,是用于连接多个逻辑上分看的网络,所谓逻辑网络是代表一个单独的网络或者是一个子网。当数据从一个子网传输到另一个子网时,可以通过路由器的路由功能来完成,因此路由器具有判断网络地址和ip路径的功能,它能在多网络互联环境中,建立灵活的连接,可用完全不同的数据分组和介质访问方法连接各种子网,路由器只接受源站或其他路由器的信息,属于网络层的一种互联设备。

  8、局域网:

    局域网,local area network ,LAN 是指某一区域内由多台计算机互联成的计算机组,一般指方圆几千米以内。局域网可以实现文件管理,应用软件共享,打印机共享,工作组内的日程安排,电子邮件和传真通信服务等功能。局域网是封闭型的,可以由办公室内两台计算机组成,也可由一个公司内的上千台计算机组成。

  9、子网掩码:

    所谓子网掩码就是表示一个子网络特征的一个参数,他在形式上等同于ip地址,也是一个32位二进制数字,他的网络部分全部为1,主机部分全部为0.

    知道了子网掩码,我们就能判断,任意两个ip地址是否处于同一个子网络内,方法是将两个ip地址与子网掩码分别进行AND运算,然后比较结果是否相同,如果是的话,就表明他们是在同一个子网络内,否则就不是。

    ip协议的作用:一是为每一台计算机分配ip地址,另一个是确定哪些地址在同一个子网络。

  2.2、TCP/UDP协议

   1、端口: 

    我们知道,一台拥有ip地址的主机可以提供许多服务,比如 web服务、ftp服务、smtp服务等,这些服务完全可以通过1个ip地址来实现,但是实际上是通过ip地址+端口号来区分不同的服务的。

   2、TCP协议

    TCP协议安全、可靠、面向连接,面向数据流形式的传输

    三次握手:首先必须由客户端发起连接的请求;接下来服务器接收到请求之后,回复给客户端两个标识,一个syn表示服务器接收到请求,一个ack表示服务器正在做准备 工作,两个标识一起回复给客户端;最后,客户端接收到服务器的回复,客户端准备连接的所有资源,开始进行连接,发送给服务器一个ack表示客户端的连接准备工作已经完成。哪句代码体现了三次握手:服务端的accept,客户端的connect。

    四次挥手:首先连接双方任意一方发起断开连接的请求,发起方发送的请求表示是我没有数据要继续发送了,可以断开连接了,但是你如果还有数据可以继续向我发送数据;接收方回复给发起方,表示接到了发起方的断开请求,开始着手准备断开事宜;接收方准备完成后,给发起方发送一个标识,表示接收方没有数据继续发送了,可以断开连接了;发起方接收到消息后,准备断开连接,回收资源。哪句代码体现了四次挥手:close()。

   3、UDP协议

    当应用程序希望通过udp与一个应用程序通信时,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能地快地把它扔到网络上。

    UDP的特点是不安全、不可靠、不建立连接、发送的是数据包,但是快。

   4、互联网协议和OSI模型

  

三 、socket概念

    1、socket是应用层与TCP/IP协议族通信的中间软件抽象层,他是一组接口。在设计模式中,socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在socket接口后面,对用户来说,一组简单的接口就是全部,让socket去组织数据,以符合指定的协议。

    2、TCP协议与UDP协议

     3、基于TCP协议的socket

 1 import socket
 2 sk = socket.socket()
 3 sk.bind(("127.0.0.1", 9090))  # 绑定地址到套接字,地址为元组形式
 4 sk.listen()    # 监听连接
 5 conn, addr = sk.accept()    # 等待接收客户端连接
 6 ret = conn.recv(1024)    # 接收客户端信息,1024个字节
 7 print(ret)     # 打印客户端发送来的信息
 8 conn.send(b"hi")   # 给客户端回复信息,bytes形式    
 9 conn.close()    # 关闭客户端套接字
10 sk.close()   # 关闭服务器套接字
TCP协议server端
1 import socket
2 sk = socket.socket()    # 创建客户端套接字
3 sk.connect(("127.0.0.1", 9090))  # 尝试使用该地址端口连接服务器
4 sk.send(b"hello")   # 发送bytes类型数据给服务端
5 ret = sk.recv(1024)  # 接收服务端发送过来的代码,最大1024个字节
6 print(ret)
7 sk.close()
TCP协议client端
 1 #加入一条socket配置,重用ip和端口
 2 import socket
 3 from socket import SOL_SOCKET,SO_REUSEADDR
 4 sk = socket.socket()
 5 sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
 6 sk.bind(('127.0.0.1',8898))  #把地址绑定到套接字
 7 sk.listen()          #监听链接
 8 conn,addr = sk.accept() #接受客户端链接
 9 ret = conn.recv(1024)   #接收客户端信息
10 print(ret)              #打印客户端信息
11 conn.send(b'hi')        #向客户端发送信息
12 conn.close()       #关闭客户端套接字
13 sk.close()        #关闭服务器套接字(可选)
socket配置,重用ip和端口

    4、基于UDP协议的socket

1 import socket
2 udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字
3 udp_sk.bind(('127.0.0.1',9000))        #绑定服务器套接字
4 msg,addr = udp_sk.recvfrom(1024)
5 print(msg)
6 udp_sk.sendto(b'hi',addr)                 # 对话(接收与发送)
7 udp_sk.close()                         # 关闭服务器套接字
UDP协议server端
1 import socket
2 ip_port=('127.0.0.1',9000)
3 udp_sk=socket.socket(type=socket.SOCK_DGRAM)
4 udp_sk.sendto(b'hello',ip_port)
5 back_msg,addr=udp_sk.recvfrom(1024)
6 print(back_msg.decode('utf-8'),addr)
UDP协议client端

    5、黏包

      注意:只有TCP有黏包现象,UDP永远不会黏包。

 1 #_*_coding:utf-8_*_
 2 from socket import *
 3 import subprocess
 4 
 5 ip_port=('127.0.0.1',8888)
 6 BUFSIZE=1024
 7 
 8 tcp_socket_server=socket(AF_INET,SOCK_STREAM)
 9 tcp_socket_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
10 tcp_socket_server.bind(ip_port)
11 tcp_socket_server.listen(5)
12 
13 while True:
14     conn,addr=tcp_socket_server.accept()
15     print('客户端',addr)
16 
17     while True:
18         cmd=conn.recv(BUFSIZE)
19         if len(cmd) == 0:break
20 
21         res=subprocess.Popen(cmd.decode('utf-8'),shell=True,
22                          stdout=subprocess.PIPE,
23                          stdin=subprocess.PIPE,
24                          stderr=subprocess.PIPE)
25 
26         stderr=res.stderr.read()
27         stdout=res.stdout.read()
28         conn.send(stderr)
29         conn.send(stdout)
30 
31 tcp - server
基于tcp协议实现的黏包-server端
 1 #_*_coding:utf-8_*_
 2 import socket
 3 BUFSIZE=1024
 4 ip_port=('127.0.0.1',8888)
 5 
 6 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 7 res=s.connect_ex(ip_port)
 8 
 9 while True:
10     msg=input('>>: ').strip()
11     if len(msg) == 0:continue
12     if msg == 'quit':break
13 
14     s.send(msg.encode('utf-8'))
15     act_res=s.recv(BUFSIZE)
16 
17     print(act_res.decode('utf-8'),end='')
18 
19 tcp - client
基于tcp协议实现的黏包-client端

      黏包的成因:因为TCP是面向连接的,面向数据流的,提供高可靠性的服务,收发两端都有一对成对的socket,因此发送端为了将多个发往接收端的包,更有效的发送到对方,使用了优化方法,Nagle算法,将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包,这样接收端就难以分辨出来了,必须提供科学的拆包机制。

      可靠黏包的TCP协议:TCP协议数据不会丢,没有收完包,下次接收,会继续上次接收的地方继续接收,已端总是在收到ack时才会清除缓冲区内容,数据是可靠的,但是会黏包。

      黏包的解决方案:

 1 #_*_coding:utf-8_*_
 2 import socket,subprocess
 3 ip_port=('127.0.0.1',8080)
 4 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 5 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 6 
 7 s.bind(ip_port)
 8 s.listen(5)
 9 
10 while True:
11     conn,addr=s.accept()
12     print('客户端',addr)
13     while True:
14         msg=conn.recv(1024)
15         if not msg:break
16         res=subprocess.Popen(msg.decode('utf-8'),shell=True,\
17                             stdin=subprocess.PIPE,\
18                          stderr=subprocess.PIPE,\
19                          stdout=subprocess.PIPE)
20         err=res.stderr.read()
21         if err:
22             ret=err
23         else:
24             ret=res.stdout.read()
25         data_length=len(ret)
26         conn.send(str(data_length).encode('utf-8'))
27         data=conn.recv(1024).decode('utf-8')
28         if data == 'recv_ready':
29             conn.sendall(ret)
30     conn.close()
31 
32 服务端
服务端的解决方案
 1 #_*_coding:utf-8_*_
 2 import socket,time
 3 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 4 res=s.connect_ex(('127.0.0.1',8080))
 5 
 6 while True:
 7     msg=input('>>: ').strip()
 8     if len(msg) == 0:continue
 9     if msg == 'quit':break
10 
11     s.send(msg.encode('utf-8'))
12     length=int(s.recv(1024).decode('utf-8'))
13     s.send('recv_ready'.encode('utf-8'))
14     send_size=0
15     recv_size=0
16     data=b''
17     while recv_size < length:
18         data+=s.recv(1024)
19         recv_size+=len(data)
20 
21 
22     print(data.decode('utf-8'))
23 
24 客户端
客户端的解决方案

使用struct解决黏包:

 1 import socket,struct,json
 2 import subprocess
 3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 4 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加
 5 
 6 phone.bind(('127.0.0.1',8080))
 7 
 8 phone.listen(5)
 9 
10 while True:
11     conn,addr=phone.accept()
12     while True:
13         cmd=conn.recv(1024)
14         if not cmd:break
15         print('cmd: %s' %cmd)
16 
17         res=subprocess.Popen(cmd.decode('utf-8'),
18                              shell=True,
19                              stdout=subprocess.PIPE,
20                              stderr=subprocess.PIPE)
21         err=res.stderr.read()
22         print(err)
23         if err:
24             back_msg=err
25         else:
26             back_msg=res.stdout.read()
27 
28 
29         conn.send(struct.pack('i',len(back_msg))) #先发back_msg的长度
30         conn.sendall(back_msg) #在发真实的内容
31 
32     conn.close()
33 
34 服务端(自定制报头)
服务端
 1 #_*_coding:utf-8_*_
 2 import socket,time,struct
 3 
 4 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 5 res=s.connect_ex(('127.0.0.1',8080))
 6 
 7 while True:
 8     msg=input('>>: ').strip()
 9     if len(msg) == 0:continue
10     if msg == 'quit':break
11 
12     s.send(msg.encode('utf-8'))
13 
14 
15 
16     l=s.recv(4)
17     x=struct.unpack('i',l)[0]
18     print(type(x),x)
19     # print(struct.unpack('I',l))
20     r_s=0
21     data=b''
22     while r_s < x:
23         r_d=s.recv(1024)
24         data+=r_d
25         r_s+=len(r_d)
26 
27     # print(data.decode('utf-8'))
28     print(data.decode('gbk')) #windows默认gbk编码
29 
30 客户端(自定制报头)
客户端

FTP作业:上传下载文件

  1 import socket
  2 import struct
  3 import json
  4 import subprocess
  5 import os
  6 
  7 class MYTCPServer:
  8     address_family = socket.AF_INET
  9 
 10     socket_type = socket.SOCK_STREAM
 11 
 12     allow_reuse_address = False
 13 
 14     max_packet_size = 8192
 15 
 16     coding='utf-8'
 17 
 18     request_queue_size = 5
 19 
 20     server_dir='file_upload'
 21 
 22     def __init__(self, server_address, bind_and_activate=True):
 23         """Constructor.  May be extended, do not override."""
 24         self.server_address=server_address
 25         self.socket = socket.socket(self.address_family,
 26                                     self.socket_type)
 27         if bind_and_activate:
 28             try:
 29                 self.server_bind()
 30                 self.server_activate()
 31             except:
 32                 self.server_close()
 33                 raise
 34 
 35     def server_bind(self):
 36         """Called by constructor to bind the socket.
 37         """
 38         if self.allow_reuse_address:
 39             self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 40         self.socket.bind(self.server_address)
 41         self.server_address = self.socket.getsockname()
 42 
 43     def server_activate(self):
 44         """Called by constructor to activate the server.
 45         """
 46         self.socket.listen(self.request_queue_size)
 47 
 48     def server_close(self):
 49         """Called to clean-up the server.
 50         """
 51         self.socket.close()
 52 
 53     def get_request(self):
 54         """Get the request and client address from the socket.
 55         """
 56         return self.socket.accept()
 57 
 58     def close_request(self, request):
 59         """Called to clean up an individual request."""
 60         request.close()
 61 
 62     def run(self):
 63         while True:
 64             self.conn,self.client_addr=self.get_request()
 65             print('from client ',self.client_addr)
 66             while True:
 67                 try:
 68                     head_struct = self.conn.recv(4)
 69                     if not head_struct:break
 70 
 71                     head_len = struct.unpack('i', head_struct)[0]
 72                     head_json = self.conn.recv(head_len).decode(self.coding)
 73                     head_dic = json.loads(head_json)
 74 
 75                     print(head_dic)
 76                     #head_dic={'cmd':'put','filename':'a.txt','filesize':123123}
 77                     cmd=head_dic['cmd']
 78                     if hasattr(self,cmd):
 79                         func=getattr(self,cmd)
 80                         func(head_dic)
 81                 except Exception:
 82                     break
 83 
 84     def put(self,args):
 85         file_path=os.path.normpath(os.path.join(
 86             self.server_dir,
 87             args['filename']
 88         ))
 89 
 90         filesize=args['filesize']
 91         recv_size=0
 92         print('----->',file_path)
 93         with open(file_path,'wb') as f:
 94             while recv_size < filesize:
 95                 recv_data=self.conn.recv(self.max_packet_size)
 96                 f.write(recv_data)
 97                 recv_size+=len(recv_data)
 98                 print('recvsize:%s filesize:%s' %(recv_size,filesize))
 99 
100 
101 tcpserver1=MYTCPServer(('127.0.0.1',8080))
102 
103 tcpserver1.run()
104 
105 
106 
107 
108 
109 
110 #下列代码与本题无关
111 class MYUDPServer:
112 
113     """UDP server class."""
114     address_family = socket.AF_INET
115 
116     socket_type = socket.SOCK_DGRAM
117 
118     allow_reuse_address = False
119 
120     max_packet_size = 8192
121 
122     coding='utf-8'
123 
124     def get_request(self):
125         data, client_addr = self.socket.recvfrom(self.max_packet_size)
126         return (data, self.socket), client_addr
127 
128     def server_activate(self):
129         # No need to call listen() for UDP.
130         pass
131 
132     def shutdown_request(self, request):
133         # No need to shutdown anything.
134         self.close_request(request)
135 
136     def close_request(self, request):
137         # No need to close anything.
138         pass
139 
140  服务端
FTP作业服务端
 1 import socket
 2 import struct
 3 import json
 4 import os
 5 
 6 
 7 
 8 class MYTCPClient:
 9     address_family = socket.AF_INET
10 
11     socket_type = socket.SOCK_STREAM
12 
13     allow_reuse_address = False
14 
15     max_packet_size = 8192
16 
17     coding='utf-8'
18 
19     request_queue_size = 5
20 
21     def __init__(self, server_address, connect=True):
22         self.server_address=server_address
23         self.socket = socket.socket(self.address_family,
24                                     self.socket_type)
25         if connect:
26             try:
27                 self.client_connect()
28             except:
29                 self.client_close()
30                 raise
31 
32     def client_connect(self):
33         self.socket.connect(self.server_address)
34 
35     def client_close(self):
36         self.socket.close()
37 
38     def run(self):
39         while True:
40             inp=input(">>: ").strip()
41             if not inp:continue
42             l=inp.split()
43             cmd=l[0]
44             if hasattr(self,cmd):
45                 func=getattr(self,cmd)
46                 func(l)
47 
48 
49     def put(self,args):
50         cmd=args[0]
51         filename=args[1]
52         if not os.path.isfile(filename):
53             print('file:%s is not exists' %filename)
54             return
55         else:
56             filesize=os.path.getsize(filename)
57 
58         head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize}
59         print(head_dic)
60         head_json=json.dumps(head_dic)
61         head_json_bytes=bytes(head_json,encoding=self.coding)
62 
63         head_struct=struct.pack('i',len(head_json_bytes))
64         self.socket.send(head_struct)
65         self.socket.send(head_json_bytes)
66         send_size=0
67         with open(filename,'rb') as f:
68             for line in f:
69                 self.socket.send(line)
70                 send_size+=len(line)
71                 print(send_size)
72             else:
73                 print('upload successful')
74 
75 
76 
77 
78 client=MYTCPClient(('127.0.0.1',8080))
79 
80 client.run()
81 
82 客户端
FTP作业客户端

     6、socket更多的方法使用

 1 服务端套接字函数
 2 s.bind()    绑定(主机,端口号)到套接字
 3 s.listen()  开始TCP监听
 4 s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来
 5 
 6 客户端套接字函数
 7 s.connect()     主动初始化TCP服务器连接
 8 s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
 9 
10 公共用途的套接字函数
11 s.recv()            接收TCP数据
12 s.send()            发送TCP数据
13 s.sendall()         发送TCP数据
14 s.recvfrom()        接收UDP数据
15 s.sendto()          发送UDP数据
16 s.getpeername()     连接到当前套接字的远端的地址
17 s.getsockname()     当前套接字的地址
18 s.getsockopt()      返回指定套接字的参数
19 s.setsockopt()      设置指定套接字的参数
20 s.close()           关闭套接字
21 
22 面向锁的套接字方法
23 s.setblocking()     设置套接字的阻塞与非阻塞模式
24 s.settimeout()      设置阻塞套接字操作的超时时间
25 s.gettimeout()      得到阻塞套接字操作的超时时间
26 
27 面向文件的套接字的函数
28 s.fileno()          套接字的文件描述符
29 s.makefile()        创建一个与该套接字相关的文件
30 
31 更多方法
socket更多方法的使用

     7、验证客户端链接的合法性

 1 #_*_coding:utf-8_*_
 2 from socket import *
 3 import hmac,os
 4 
 5 secret_key=b'linhaifeng bang bang bang'
 6 def conn_auth(conn):
 7     '''
 8     认证客户端链接
 9     :param conn:
10     :return:
11     '''
12     print('开始验证新链接的合法性')
13     msg=os.urandom(32)
14     conn.sendall(msg)
15     h=hmac.new(secret_key,msg)
16     digest=h.digest()
17     respone=conn.recv(len(digest))
18     return hmac.compare_digest(respone,digest)
19 
20 def data_handler(conn,bufsize=1024):
21     if not conn_auth(conn):
22         print('该链接不合法,关闭')
23         conn.close()
24         return
25     print('链接合法,开始通信')
26     while True:
27         data=conn.recv(bufsize)
28         if not data:break
29         conn.sendall(data.upper())
30 
31 def server_handler(ip_port,bufsize,backlog=5):
32     '''
33     只处理链接
34     :param ip_port:
35     :return:
36     '''
37     tcp_socket_server=socket(AF_INET,SOCK_STREAM)
38     tcp_socket_server.bind(ip_port)
39     tcp_socket_server.listen(backlog)
40     while True:
41         conn,addr=tcp_socket_server.accept()
42         print('新连接[%s:%s]' %(addr[0],addr[1]))
43         data_handler(conn,bufsize)
44 
45 if __name__ == '__main__':
46     ip_port=('127.0.0.1',9999)
47     bufsize=1024
48     server_handler(ip_port,bufsize)
49 
50 服务端
验证客户端链接合法性--服务端
 1 #_*_coding:utf-8_*_
 2 __author__ = 'Linhaifeng'
 3 from socket import *
 4 import hmac,os
 5 
 6 secret_key=b'linhaifeng bang bang bang'
 7 def conn_auth(conn):
 8     '''
 9     验证客户端到服务器的链接
10     :param conn:
11     :return:
12     '''
13     msg=conn.recv(32)
14     h=hmac.new(secret_key,msg)
15     digest=h.digest()
16     conn.sendall(digest)
17 
18 def client_handler(ip_port,bufsize=1024):
19     tcp_socket_client=socket(AF_INET,SOCK_STREAM)
20     tcp_socket_client.connect(ip_port)
21 
22     conn_auth(tcp_socket_client)
23 
24     while True:
25         data=input('>>: ').strip()
26         if not data:continue
27         if data == 'quit':break
28 
29         tcp_socket_client.sendall(data.encode('utf-8'))
30         respone=tcp_socket_client.recv(bufsize)
31         print(respone.decode('utf-8'))
32     tcp_socket_client.close()
33 
34 if __name__ == '__main__':
35     ip_port=('127.0.0.1',9999)
36     bufsize=1024
37     client_handler(ip_port,bufsize)
38 
39 客户端(合法)
验证客户端链接合法性--客户端(合法)

四、socketserver

 1 import socketserver
 2 class Myserver(socketserver.BaseRequestHandler):
 3     def handle(self):
 4         self.data = self.request.recv(1024).strip()
 5         print("{} wrote:".format(self.client_address[0]))
 6         print(self.data)
 7         self.request.sendall(self.data.upper())
 8 
 9 if __name__ == "__main__":
10     HOST, PORT = "127.0.0.1", 9999
11 
12     # 设置allow_reuse_address允许服务器重用地址
13     socketserver.TCPServer.allow_reuse_address = True
14     # 创建一个server, 将服务地址绑定到127.0.0.1:9999
15     server = socketserver.TCPServer((HOST, PORT),Myserver)
16     # 让server永远运行下去,除非强制停止程序
17     server.serve_forever()
18 
19 server端
socketserver服务器端
 1 import socket
 2 
 3 HOST, PORT = "127.0.0.1", 9999
 4 data = "hello"
 5 
 6 # 创建一个socket链接,SOCK_STREAM代表使用TCP协议
 7 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
 8     sock.connect((HOST, PORT))          # 链接到客户端
 9     sock.sendall(bytes(data + "\n", "utf-8")) # 向服务端发送数据
10     received = str(sock.recv(1024), "utf-8")# 从服务端接收数据
11 
12 print("Sent:     {}".format(data))
13 print("Received: {}".format(received))
14 
15 client
socketserver客户端

猜你喜欢

转载自www.cnblogs.com/bug-ming/p/9383960.html