socket编程,客户端,服务端python笔记

服务端:

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()

你可能感兴趣的:(python,开发语言)