socket :套接字
socket 是Python中的内置模块。
一:socket例子
1.socket简单通信
server.py 服务端文件
# server.py
import socket
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 这两个参数是默认
con_ip = ("127.0.0.1",8848) # 一个元组,内容是 ip + 端口
sk.bind(con_ip) # 绑定ip
sk.listen(5)
conn,addr = sk.accept() # 监听 返回一个通道,以及访问者的ip和端口号
msg = conn.recv(1024) # 读取客户端传来的信息,类型是字节,一次最大读取1024个字节(该字节可以修改,最好为1024的倍数)
conn.send(b'hello') # 向客户端发送字节类型的信息
conn.close() # 与该访问者的 连接通道断开
sk.close() # 服务器关闭
client.py 客户端文件
# client.py
import socket
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
ip_con = ("127.0.0.1",8848) # 服务端的ip 和 端口号
sk.coonect(ip_con)
sk.send(b"hello") # 向服务端发送字节类型信息
msg = sk.recv(1024) # 最大接受1024字节的信息。同服务端的recv
print(msg.decode()) # 将字节编码转换
sk.close()
2.socket循环通信
server.py 服务端文件
# server.py
import socket
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 这两个参数是默认
con_ip = ("127.0.0.1",8848) # 一个元组,内容是 ip + 端口
sk.bind(con_ip) # 绑定ip
sk.listen(5)
conn,addr = sk.accept() # 监听 返回一个通道,以及访问者的ip和端口号
while 1:
msg = conn.recv(1024) # 读取客户端传来的信息,类型是字节,一次最大读取1024个字节(该字节可以修改,最好为1024的倍数)
conn.send(b'hello') # 向客户端发送字节类型的信息
if msg.decode() == "q":
break
conn.close() # 与该访问者的 连接通道断开
sk.close() # 服务器关闭
client.py 客户端文件
# client.py
import socket
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
ip_con = ("127.0.0.1",8848) # 服务端的ip 和 端口号
sk.coonect(ip_con)
while 1:
sk.send(b"hello") # 向服务端发送字节类型信息
msg = sk.recv(1024) # 最大接受1024字节的信息。同服务端的recv
print(msg.decode()) # 将字节编码转换
if msg.decode() == "q":
break
sk.close()
3.socket连接连接
server.py 服务端文件
# server.py
import socket
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 这两个参数是默认
con_ip = ("127.0.0.1",8848) # 一个元组,内容是 ip + 端口
sk.bind(con_ip) # 绑定ip
sk.listen(5)
while 1:
conn,addr = sk.accept() # 监听 返回一个通道,以及访问者的ip和端口号
while 1:
msg = conn.recv(1024) # 读取客户端传来的信息,类型是字节,一次最大读取1024个字节(该字节可以修改,最好为1024的倍数)
conn.send(b'hello') # 向客户端发送字节类型的信息
if msg.decode() == "q":
break
conn.close() # 与该访问者的 连接通道断开
sk.close() # 服务器关闭
client.py 客户端文件 同 2.socket循环通信 的 client.py 文件
4.socket远程执行命令
server.py 服务端文件
# server.py
import socket
import subprocess
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
con_ip = ("127.0.0.1",8848)
sk.bind(con_ip)
sk.listen(5)
conn,addr = sk.accept()
msg = conn.recv(1024).decode()
ret = subprocess.Popen(msg,shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE) # subprocess可以在当前程序中执行其他程序或命令,创建并返回一个子进程,并在这个进程中执行指定的程序。
stdout = ret.stdout.read() # 命令正确的输出信息
stderr = ret.stderr.read() # 命令错误的输出信息
len_num = str(len(stdout+stderr))
conn.send(len_num.encode()) # 先将 长度发送出去
conn.recv(1024).decode() # 随便接受一个信息
conn.send(stdout+stderr) # 再将全部信息发送
conn.close()
sk.close()
client.py 客户端文件
# client.py
import socket
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
ip_con = ("127.0.0.1",8848)
sk.coonect(ip_con)
sk.send(b"ipconfig")
len_num = sk.recv(1024).decode()
sk.send(b"1")
msg = sk.recv(int(len_num)).decode('gbk') # windows 默认编码格式 gbk
print(msg)
sk.close()
二:socket黏包现象
1.服务端或者客户端连续发送两个send
# server.py
import socket
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
con_ip = ("127.0.0.1",8848)
sk.bind(con_ip)
sk.listen(5)
conn,addr = sk.accept()
msg = conn.recv(1024)
conn.send(b'hello')
conn.send(b'hello') # 此时会有问题。 客户端接收到的将是 hellohello 信息
conn.close()
sk.close()
2.send的字节数大于对方recv接受的最大字节数 也会出现
# client.py
import socket
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
ip_con = ("127.0.0.1",8848)
sk.coonect(ip_con)
sk.send(b"假设对方的recv 后接受的最大字节数为 1024,而我在这里发送的字节数为 1025,则会出现黏包现象,数据展示不全,丢失部分数据")
sk.close()