服务端:
from socket import *
import threading
from multiprocessing import *
ip = '127.0.0.1' # 可以是0.0.0.0,为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。服务器IP设置必须为0.0.0.0不然其他主机连不#上。
# 因为有些机子不止一块网卡,多网卡的情况下,这个就表示所有网卡ip地址的意思.
# INADDR_ANY就是指定地址为0.0.0.0的地址,客户端connect时,不能使用INADDR_ANY选项。必须指明要连接哪个服务器IP
port = 3333
try:
listens = socket(AF_INET, SOCK_STREAM) # 创建socket,AF_INET指使用IPv4地址
'''
int socket(int domain, int type, int protocol)
domain
参数表示套接字要使用的协议簇,协议簇的在“linux/socket.h”里有详细定义,常用的协议簇:
AF_UNIX(本机通信)
AF_INET(TCP/IP – IPv4)
AF_INET6(TCP/IP – IPv6)
type
“type”参数指的是套接字类型,常用的类型有:
SOCK_STREAM(TCP流)
SOCK_DGRAM(UDP数据报)
SOCK_RAW(原始套接字)
protocol
协议“protocol”一般设置为“0”,就是说在已经确定套接字使用的协议簇和类型时,这个参数的值就为0。
但是有时候创建初始套接字时,在domain参数未知情况下,即不清楚协议簇和类型时,protocol参数可以用来确定协议的种类。
返回值
当套接字创建成功时,返回套接字,失败返回“-1”,错误代码则写入“errno”中。
'''
listens.bind((ip, port)) # 绑定IP地址和端口
'''
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
(1)参数 sockfd ,需要绑定的socket。
(2)参数 addr ,存放了服务端用于通信的地址和端口。
(3)参数 addrlen ,表示 addr 结构体的大小
(4)返回值:成功则返回0 ,失败返回-1,错误原因存于 errno 中。如果绑定的地址错误,或者端口已被占用,bind 函数一定会报错,否则一般不会返回错误。
'''
listens.listen(5)
# listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。
# socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。
except:
print("服务器启动失败")
else:
print('服务器启动成功,等待连接')
datas, addr = listens.accept()
print('欢迎客户端:', addr)
# TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()、
# connect()之后就向TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,
# 这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。
# int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
# accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,
# 用于返回客户端的协议地址,第三个参数为客户端协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,
# 代表与返回客户的TCP连接。
#
# connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,
# 第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。
# socket.gethostbyname( host )参数为一个域名,返回域名的IP。
def recv111(datas, event1):
while True:
receive = datas.recv(1024) # 接收客户端信息,指定接收字节大小
if not receive or (receive.decode() == 'exit'):
break
receive_decode = receive.decode()
print('客户端:', receive_decode)
print('客户端已退出')
event1.set()
def send111(datas, event1):
while True:
tosend_serv = input("")
datas.sendall(tosend_serv.encode())
if event1.is_set():
break
#bytes.decode(encoding="utf-8", errors="strict")
# str.encode(encoding="utf-8", errors="strict")编码后是字节码
# 其中的encoding是指在解码编码过程中使用的编码格式,errors是指错误的处理方案。
event1 = Event()
thread2 = threading.Thread(target=send111, args=(datas, event1))
thread1 = threading.Thread(target=recv111, args=(datas, event1,))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
datas.close()
listens.close()
客户端:
from socket import *
import threading
from multiprocessing import *
ip='127.0.0.1'
port=3333
try:
clients=socket(AF_INET,SOCK_STREAM)
clients.connect((ip,port))
except:
print('服务端连接失败')
else:
print('服务端连接成功')
def send222(clients,event1):
while True:
tosend=input("")
clients.sendall(tosend.encode())
if event1.is_set()or (tosend=='exit'):
break
def recv222(clients,event1):
while True:
receive=clients.recv(1024)
if not receive:
break
print("服务器:",receive.decode())
print("服务器关闭")
event1.set()
event1=Event()
thread1=threading.Thread(target=send222,args=(clients,event1,))
thread2=threading.Thread(target=recv222,args=(clients,event1,))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
clients.close()
socket编程Windows下传输文件(视频,文件,图片)(其他类型更改一下即可):
传输函数:
elif tosend_serv == '传输文件':
send_file(datas)
def send_file(datas):
path_file = os.path.abspath(__file__)
path_dir = os.path.dirname(path_file)
path = os.path.join(path_dir, '第一个传输文件', 'C铭.mp4')
file_size = os.stat(path).st_size
line1 = os.path.basename(path)+'|'+str(file_size)
datas.send(line1.encode(encoding='utf-8'))
sum = 0
with open(path, 'rb')as f:
print('进入文件传输循环')
while sum != file_size:
data = f.read(1024)
datas.sendall(data)
sum += len(data)
print('文件传输完成!')
datas.send('传输完成'.encode())
接收函数:
elif receive.decode()=='传输文件':
receive_file(clients)
def receive_file(clients):
path_file = os.path.abspath(__file__)
path_dir = os.path.dirname(path_file)
file_name, file_size = clients.recv(1024).decode(encoding='utf-8').split('|')
file_size = int(file_size)
path = os.path.join(path_dir, '接收文件', file_name)
sum = 0
with open(path, 'wb')as f:
print('进入文件接收循环')
while sum < file_size :
data = clients.recv(1024)
f.write(data)
sum += len(data)
print('文件接收完成')
导出数据库聊天记录:
from sqlalchemy import create_engine
import csv
engine = create_engine(
"mysql+pymysql://root:@localhost:3307/test", echo=True)
cursor = engine.connect()
res = cursor.execute('select * from talk_history;').fetchall()
with open('down_history.csv', 'w',newline='')as fi:
i = csv.writer(fi)
for l in res:
i.writerow(l)
cursor.close()
engine.dispose()