网络编程

socket模块

套接字模块是一个非常简单的基于对象的接口,提供对低层BSD套接字样式网络的访问。使用该模块可以实现客户机和服务器套接字。

要在 python 中建立具有 TCP 和流套接字的简单服务器需要使用 socket 模块。利用该模块包含的函数和类定义可生成通过网络通信的程

序。一般来说,建立服务器连接需要6个步骤。

 

1.创建 socket 对象

创建 socket 对象:socket.socket [ ( family [ , type [ , protocol ] ] ])

family:可以是 AF_UNIX ( UNIX 域,用于同一台机器上的进程间通信),也可以是 AF_INET ( 对于 IPv4 协议的 TCP 和 UDP )或 AF_INET6 ( 对于 IPV6 )。

               family 参数指定调用者期待返回的套接口地址结构类型。 family 的值包据3种:AF_INET,AF_INET6 和  AF_UNSPEC。

type:套接字类型可以根据面向连接和非连接分为 SOCK_STREAM(流套接字)或 SOCK_DGRAM(数据报文套接字)。

protocol:一般不填,默认为0

 

2.将 socket 绑定(指派)到指定地址上:socket.bind(address)。

address 必须是一个双元素元组 ( ( host , port ) ),参数为主机名或 IP 地址+端口号。如果端口号正在被使用或保留,主机名或 IP 地址错误,就会引发 sock.error 异常

 

3.绑定后必须准备好套接字,以便接受连接请求:socket.listen ( backlog )

backlog 用于指定最多连接数,至少为1,接到连接请求后,这些请求必须排队,如果队列已满,就拒绝请求。

 

4.服务器套接字通过 socket 的 accept 方法等待客户请求一个连接:connection,address = socket.accept()

调用 accept 方法时,socket 会进入等待(或阻塞)状态。客户请求连接时,accept 方法建立连接并返回服务器。 accept 方法返回一个含有两个元素的元组,如(connection,address)。

第一个元素 ( connection )是新的 socket 对象,服务器通过它与客户通信;第二个元素 ( address)就客户的互联网地址。

 

5.处理阶段,服务器和客户通过 send 和 recv 方法通信(传输数据)

服务器调用 send,并采用字符串形式向客户发送信息。send 方法返回已发送的字符个数。服务器使用 recv 方法从客户接收信息。调用 recv 时,必须指定一个整数控制本次调用所接收的最

大数据量。recv 方法在接收数据时会进入 blocket 状态,最后返回一个字符串,用于表示收到的数据。如果发送的量超过 recv 允许的量,数据就会被截断。多余的数据将缓冲于接收端。以后

调用 recv时,多余的数据会从缓冲区删除。

 

6.传输结束,服务器调用 socket 的 close 方法以关闭连接

通信结束后只须使用 socket.close 关闭连接即可

 

UDP服务端单线程

 1 import socket
 2 
 3 #1.创建套接字
 4 udp_s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
 5 
 6 #2.绑定IP和端口号
 7 udp_s.bind(('192.168.1.102',4395))
 8 
 9 while True:
10     #接收消息
11     #data是从客户端发送过来的消息,addr是元组格式,存储IP和端口号
12     data,addr = udp_s.recvfrom(1025)
13     print(addr)
14     #打印出客户端发送过来的消息,data.decode('utf-8,'):将字符转为中文格式
15     print(data.decode('utf-8,'),addr)
16     #udp_s.sendto:发送消息。
17     udp_s.sendto('服务器发送的消息'.encode('utf-8'),addr)
18 
19 #关闭套接字
20 udp_s.close()

 

UDP客户端单线程

 1 import socket
 2 
 3 #创建套接字
 4 udp_c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
 5 
 6 #绑字端口号
 7 udp_c.bind(('192.168.1.102',6969))
 8 
 9 sendData = input('<<:')
10 
11 #发送消息,('192.168.1.102',4395)要和服务端的 udp_s.bind(('192.168.1.102',4395)) 个致
12 udp_c.sendto(sendData.encode('utf-8'),('192.168.1.102',4395))
13 
14 #接收消息
15 data,addr = udp_c.recvfrom(1024)
16 print(data.decode('utf-8'),addr)
17 udp_c.close()

 

UDP服务端多线程

 1 import socket,threading
 2 
 3 #1.创建套接字
 4 udp_s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
 5 
 6 def rc():
 7     global addr
 8     #接收消息
 9     #data是从客户端发送过来的消息,addr是元组格式,存储IP和端口号
10     data,addr = udp_s.recvfrom(1024)
11     print(addr)
12     #打印出客户端发送过来的消息,data.decode('utf-8,'):将字符转为中文格式
13     print(data.decode('utf-8,'),addr)
14 
15 def st():
16     sendData = input('<<:')
17     #udp_s.sendto:发送消息。
18     udp_s.sendto(sendData.encode('utf-8'),addr)
19 
20 
21 #2.绑定IP和端口号
22 udp_s.bind(('192.168.1.102',4363))
23 
24 while True:
25 
26     t1 = threading.Thread(target = rc)
27     t2 = threading.Thread(target = st)
28     t1.start()
29     t2.start()
30     t1.join()
31     t2.join()
32 
33 
34 #关闭套接字
35 udp_s.close()

 

UDP客户端多线程

 1 import socket,threading
 2 
 3 #创建套接字
 4 udp_c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
 5 
 6 #绑字端口号
 7 udp_c.bind(('192.168.1.102',6924))
 8 
 9 def st():
10     while True:
11         #input 消息输入框
12         sendData = input('<<:')
13 
14         #发送消息,('192.168.1.102',4395)要和服务端的 udp_s.bind(('192.168.1.102',4395)) 个致
15         udp_c.sendto(sendData.encode('utf-8'),('192.168.1.102',4363))
16 
17 def rc():
18     while True:
19         #接收消息
20         data,addr = udp_c.recvfrom(1024)
21         print(data.decode('utf-8'),addr)
22 
23 #发送消息线程
24 t1 = threading.Thread(target = st)
25 #接收消息线程
26 t2 = threading.Thread(target = rc)
27 
28 t1.start()
29 t2.start()
30 t1.join()
31 t2.join()
32 udp_c.close()

 

HTTP协议规定post提交的数据必须放在消息主体中,但是协议并没有规定必须使用什么编码方式。服务端通过是根据请求头中的Content-Type

字段来获知请求中的消息主体是用何种方式进行编码,再对消息主体进行解析。具体的编码方式包括: application/x-www-form-urlencoded 最

常见post提交数据的方式,以form表单形式提交数据。 application/json 以json串提交数据。 multipart/form-data 一般使用来上传文件。

 

http页面取理请求并返回数据

 1 import socket
 2 #处理请求的方法
 3 def head():
 4     b1 = s.recv(1)  # G
 5     b2 = b''
 6     str1 = b''
 7     while b2 != b'\r' and b1 != b'\n':
 8         b2 = b1  # b2 = T 1 \r
 9         b1 = s.recv(1)  # E T '' \n
10         str1 += b2  # GET \r
11     print(str1)
12 
13 
14 # 返回数据
15 def sendData():
16     # 返回数据
17     # ---英文字符--------------------------------------------------------
18     sendata = 'hello\r\n'
19     s.send('HTTP/1.1 200 OK\r\n'.encode('ASCII'))
20     s.send(str(len(sendata)).encode('ASCII'))
21     s.send('Content-Type: text/html\r\n'.encode('ASCII'))
22     s.send('\r\n'.encode('ASCII'))
23     s.send(sendata.encode('ASCII'))
24     # ---中文字符--------------------------------------------------
25     # 返回数据,按照http响应报文的结构返回数据
26     # sendata = '页面不存在\r\n'
27     # s.send('HTTP/1.1 200 OK\r\n'.encode('utf-8'))
28     # s.send(str(len(sendata)).encode('utf-8'))
29     # s.send('Content-Type: text/html\r\n'.encode('utf-8'))
30     # s.send('\r\n'.encode('utf-8'))
31     # s.send(sendata.encode('utf-8'))
32 #创建套接字
33 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
34 
35 #绑定地址
36 sock.bind(('',8082))
37 #监听
38 sock.listen()
39 #接收
40 s,addr = sock.accept()
41 
42 #调用--处理请求的方法
43 head()
44 # 调用返回数据
45 sendData()
46 #简单方法重组请求头
47 data = s.recv(1024).
48 Data = data.decode('ASCII')
49 list1 = Data.split('\r\n')
50 print(list1)
51 
52 s.close()
53 sock.close()
54 
55 #启动本页面,然后在浏览器地址栏输入:http://127.0.0.1:8080/

 

实例:类的方法http页面取理请求并返回数据(共4个文件)

1.主文件名:webServer.py

 1 import socket,threading
 2 from sockHeadHandler import SockHanDler
 3 from pzfile import PzFile
 4 class WebServer:
 5     #初始化套接字,等待客户连接
 6     def __init__(self):
 7         self.skt = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 8         self.skt.bind((PzFile.ip,PzFile.port))
 9         self.skt.listen()
10         #定义主程序启动入口
11     def start(self):
12         # s,addr = self.skt.accept()
13         # #处理头部信息,和返回信息
14         # # headhandler = SockHanDler(s)
15         # # headhandler.startHead()
16         # # s.close()
17         while True:
18             #处理头部信息 和返回信息
19             s,addr = self.skt.accept()
20             if s:
21                 headhandler = SockHanDler(s)
22                 #开启线程处理多个请求(并发)
23                 t1 = threading.Thread(target = headhandler.startHead)
24                 t1.start()
25                 t1.join()
26                 s.close()
27 
28 if __name__ == '__main__':
29     #实例化
30     ws = WebServer()
31     #启动接收
32     ws.start()

 

 

2.类模块文件名:sockHeadHandler.py

 1 from pzfile import PzFile
 2 import os
 3 class SockHanDler:
 4     #1.初始化参数
 5     def __init__(self,s):
 6         self.s = s
 7 
 8     #2.程序的入口
 9     def startHead(self):
10         #调用头处理
11         self.headHandler()
12 
13         #调用返回,第4步
14         #self.sendHandler()
15 
16         #返回指定页面,第5步
17 
18         self.sendpage('index.html')
19 
20     #3.头部处理方法
21     def headHandler(self):
22         headInfo = self.__getHead()
23         print(headInfo)
24 
25     #4.返回信息处理方法
26     def sendHandler(self):
27         sendData = 'Hello'
28 
29     #5.返回页面方法
30     def sendpage(self,file):
31         #拼接文件路径
32         file_path = os.path.join(PzFile.base_path,file)
33         #读取文件
34         with open(file_path,mode='r',encoding='utf-8') as f:
35             html = f.read()
36             self.__sendRst(html)
37 
38     #================================================
39     #2-1.获取头部处理逻辑
40     def __getHead(self):
41         # 简单方法重组请求头
42         data = self.s.recv(1024)
43         Data = data.decode('utf-8')
44         list1 = Data.split('\r\n')
45         return list1
46     #2-2.返回信息的方法
47     def __sendRst(self,data):
48         self.s.send((PzFile.http_v + PzFile.http_s + PzFile.http_ok + PzFile.rn).encode('utf-8'))
49         self.s.send((PzFile.content_type + PzFile.rn).encode('utf-8'))
50         self.s.send(PzFile.rn.encode('utf-8'))
51         self.s.send(data.encode('utf-8'))

 

3.类模块配置文件:pzfile.py

 1 class PzFile:
 2     ip = '127.0.0.1'
 3     port = 8092
 4 
 5     #返回信息
 6     http_v = 'HTTP/1.1'
 7     http_s = '200'
 8     http_ok = 'OK'
 9 
10     content_type ='Content-Type: text/html'
11     rn = '\r\n'
12 
13     #添加文件目录,复制路径-在webApp目录点击右键-Copy path
14     base_path = r'C:\Users\Administrator\PycharmProjects\untitled\webApp'

 

4.网页文件:webApp/index.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <h1>首页</h1>
 9     <p>欢迎来到我的网站</p>
10     <img src = "" alt = "这是美女大图">
11     <a href = "https://www.baidu.com">点我跳百度</a>
12 </body>
13 </html>

 

转载于:https://www.cnblogs.com/lws865/p/10925917.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值