1.socket是什么?
是电脑网络中进程间数据流的端点
操作系统的通信机制
应用程序通过socket进行网络数据的传输
2.通信过程与TCP三次握手相似
3.socket通信方式
分为:UDP和TCP
4.socket参数
type:类型
socket.SOCK_STREAM 流式socket,for TCP(默认)
socket.SOCK_DGRAM 数据报式socket,for UDP
socket.SOCK_RAW 原始套接字 (可以忽略)
socket.SOCK_RDM 可靠UDP形式 (可以忽略)
socket.SOCK_SEQPACKET 可靠的连续数据包服务 (可以忽略)
创建服务器
import random
import socket
# 创建实例
sk = socket.socket()
# 定义绑定的ip和端口
ip_port = ('127.0.0.1',8888) # 元祖
# 绑定监听
sk.bind(ip_port)
# 最大连接数
sk.listen(5) # 最少是1
# 5代表 挂起的连接数是5,同时有5个请求来,
# 可以同时回应,正在处理的程序只有一个,其他4个程序处于等待状态
# 如果多于5个服务器会直接拒绝第六个请求
# 不断接受数据
while True:
# 提示信息
print('正在接受 数据.......')
# 接受数据:传回两个参数一个是连接对象,一个是客户端地址
# 接受数据是阻塞状态
conn,address = sk.accept()
# 定义信息
msg = '连接成功'
# 返回信息
"""
注意:
python3.x以上,网络数据的发送接受都是byte类型
如果发送的数据是str型的则需要进行编码,python2 不需要
"""
conn.send(msg.encode())
# 不断接受客户端发来的消息
while True:
# 接受客户端消息
data = conn.recv(1024) # 接受1024字节
# 打印数据
print(data.decode())
# 接受到退出指令
if data == b'exit':
break
# 处理客户端数据
conn.send(data)
# 发送随机数信息
conn.send(str(random.randint(1,1000)).encode())
# 直接连接的关闭,主动关闭连接
# 通信一次就关闭
conn.close()
创建客户端
import socket
# 实例的初始化
client = socket.socket()
# 访问的服务器端的ip和端口
ip_port = ('127.0.0.1',8888)
# 连接主机
client.connect(ip_port)
while True:
# 连接主机信息
data = client.recv(1024) # 接受数据为1024个字节
# 打印接收到的数据
# 此处的byte型数据特指python3.x以上 ,py2不用
print(data.decode())
# 输入发送的消息
msg_input = input('请输入发送的消息:')
# 消息发送
client.send(msg_input.encode())
if msg_input == 'exit':
break
data = client.recv(1024)
print(data.decode())
UDP
socket_server_udp
import socket
# 创建实例
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 不指定参数默认ipv4、tcp流式发送方式
# 定义绑定的ip和port
ip_port = ('127.0.0.1',7888)
# 绑定监听
sk.bind(ip_port)
# 不断循环接受数据
while True:
# 接受数据
data = sk.recv(1024)
# 打印数据
print(data.decode())
# UDP的server并没有关闭连接的方法,因为UDP是一种不可靠的通信方式
# 之间并不进行三次握手过程
# UDP的通信方式:
# 服务器接受客户端的数据,并进行客户端的发送。服务器端接受客户端的和数据并根据需要返回给客户端
# 同时,并不与客户端建立安全的通道,保证数据包的安全通信
socket_client_udp
import socket
# 定义实例
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 定义需要连接的服务器ip和port
ip_port = ('127.0.0.0.1', 7888)
# 循环数据的输入
while True:
# 输入发送的信息
msg_input = input('请输入发送的消息:')
# 退出循环的条件
if msg_input == 'exit':
break
# 数据发送
sk.sendto(msg_input.encode(), ip_port)
# 发送关闭信息(主动发送)
sk.close()
socket非阻塞模块
服务器端对多个客户端连接
import random
import socketserver
# 定义一个类
class MyServer(socketserver.BaseRequestHandler):
# 这三个方法是系统自带的
# 通过自己定义的类,去进行三个方法的定义,以覆盖原来的方法
# 执行顺序setup,handle,finish
# 如果handle方法出现报错,则会进行跳过
# setup方法和finish方法无论如何都会执行的
# 一般情况下不去进行定义setup方法和finish方法,只会对handle方法的重写
def setup(self):
pass
def handle(self):
# 定义连接变量
conn = self.request
# 发送信息定义
msg = 'Hello world'
# 信息发送
conn.send(msg.encode())
# 进入循环,不断接受客户端的消息
while True:
# 接受客户端消息
data = conn.recv(1024*64)
# 打印消息
print(data.decode())
# 接受exit 则进行循环退出
if data == 'exit':
break
conn.send(data)
conn.send(str(random.randint(1,1000)).encode())
conn.close()
def finish(self):
pass
if __name__ == '__main__':
# 创建多线程实例
# 传入监听的ip、端口,和自己定义的类
server = socketserver.ThreadingTCPServer(('127.0.0.1',8888),MyServer)
# 开启异步多线程,等待客户端的连接
# server.handle_request() 只处理一个请求
server.serve_forever() # 处理多个请求,永远执行
文件上传
文件接收.py
import socket
sk = socket.socket()
ip_port = ('127.0.0.1',8999)
sk.bind(ip_port)
sk.listen(5)
while True:
# 等待客户端连接
conn,address = sk.accept()
# 一直使用当前连接数据发送
# 直到结束标志出现
while True:
with open('file', 'ab') as f:
# 接收数据
data = conn.recv(1024)
if data == b'quit':
break
# 写入文件
f.write(data)
# 接收完成标志
conn.send('success'.encode())
# 打印提示信息
print('文件接收完成')
# 关闭连接
sk.close() # 没有生效
文件上传.py
import socket
sk = socket.socket()
ip_port = ('127.0.0.1',8999)
sk.connect(ip_port)
# 文件上传
# 打开文件
with open('socket_server_tcp2.py','rb') as f:
# 按每一段分隔文件
for i in f:
# 数据上传
sk.send(i)
data = sk.recv(1024)
if data != b'success':
break
# 给服务器端发送结束信号
sk.send('quit'.encode())