双端通信总结

该代码实现了一个基于TCP/IP协议的图片文件传输系统,包括服务端和客户端。服务端监听特定IP和端口,接收客户端发送的图片文件信息,然后接收并保存图片。客户端则向服务端发送文件信息,然后发送图片文件。此外,还包含了处理接收数据和发送文件的函数。
摘要由CSDN通过智能技术生成
import socket
import os
import sys
import struct

这部分代码导入了需要使用的模块,包括 socketossysstruct

def socket_service_image():

定义了一个名为 socket_service_image 的函数,用于处理图片文件的服务端操作。

 

try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(("192.168.10.156", 6666)) s.listen(10) except socket.error as msg: print(msg) sys.exit(1)

try 块中,创建了一个 TCP/IP 的套接字对象 s,并设置了套接字选项 SO_REUSEADDR,允许重用地址。然后,将套接字绑定到指定的 IP 地址和端口号上,并开始监听连接请求。如果出现异常,会打印错误信息并退出程序。

print("Wait for Connection..................")

打印等待连接的提示信息。

 

while True: sock, addr = s.accept() deal_image(sock, addr)

进入一个无限循环,使用 s.accept() 接受客户端的连接请求,并返回一个新的套接字 sock 和客户端的地址 addr。然后,调用 deal_image(sock, addr) 函数处理接收到的图片文件。

 

def deal_image(sock, addr):

定义了一个名为 deal_image 的函数,用于处理接收到的图片文件。

 

print("Accept connection from {0}".format(addr))

打印接受到连接的提示信息,并显示客户端的地址。

 

while True: fileinfo_size = struct.calcsize("128sq") buf = sock.recv(fileinfo_size) if buf: filename, filesize = struct.unpack("128sq", buf) fn = filename.decode().strip("\x00") new_filename = os.path.join("./", "new_" + fn) recvd_size = 0 fp = open(new_filename, "wb") while not recvd_size == filesize: if filesize - recvd_size > 1024: data = sock.recv(1024) recvd_size += len(data) else: data = sock.recv(1024) recvd_size = filesize fp.write(data) fp.close() sock.close() break

deal_image 函数中,进入一个无限循环。首先,通过 struct.calcsize("128sq") 计算出接收数据包的固定字节大小。然后,使用 sock.recv(fileinfo_size) 接收一个固定大小的数据包,并赋值给变量 buf

如果接收到数据,使用 struct.unpack("128sq", buf) 解包数据包,取出文件名和文件大小。将文件名进行解码并去除空字符(\x00),然后生成一个新的文件名路径。

接下来,初始化接收的数据大小 recvd_size 为 0,并打开新文件以二进制写入模式。

然后,进入一个循环,接收数据并写入文件,直到接收的数据大小与文件大小相等。如果剩余要接收的数据大于 1024 字节,每次接收 1024 字节的数据,并更新接收的数据大小。否则,一次性接收剩余的数据,并将接收的数据大小设置为文件大小。

最后,关闭文件和套接字,并跳出循环。

 

if __name__ == '__main__': socket_service_image()

如果当前脚本是作为主程序运行,则调用 socket_service_image() 函数进行图片文件的服务端操作。

import socket
import os
import sys
import struct

这部分代码导入了需要使用的模块,包括 socketossysstruct

 

def sock_client_image():

定义了一个名为 sock_client_image 的函数,用于处理图片文件的客户端操作。

 

while True: try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("192.168.10.156", 6666)) except socket.error as msg: print(msg) print(sys.exit(1))

进入一个无限循环,首先创建了一个 TCP/IP 的套接字对象 s,然后使用 s.connect() 方法连接到指定的服务器地址和端口号。如果连接出现异常,会打印错误信息并退出程序。

 

filepath = input("input the file:")

提示用户输入要发送的文件路径。

 

fhead = struct.pack(b"128sq", bytes(os.path.basename(filepath), encoding="utf-8"), os.stat(filepath).st_size) s.send(fhead)

使用 struct.pack() 方法打包文件名和文件大小为一个固定大小的字节流,并使用 s.send() 方法发送给服务器。

 

fp = open(filepath, "rb") while True: data = fp.read(1024) if not data: print("{0} send over...".format(filepath)) break s.send(data) s.close()

打开要发送的文件,并进入一个循环,每次读取 1024 字节的数据并发送给服务器,直到文件读取完毕。最后,关闭文件和套接字。

 

if __name__ == '__main__': sock_client_image()

如果当前脚本是作为主程序运行,则调用 sock_client_image() 函数进行图片文件的客户端操作。

import os

导入了需要使用的 os 模块。

import struct

导入了需要使用的 struct 模块。

from socket import *

socket 模块中导入了所有内容。

from threading import Thread

threading 模块中导入了 Thread 类。

def recv_data(client_socket, client_info):

定义了一个名为 recv_data 的函数,用于处理接收客户端数据的操作。

while True: recv_data = client_socket.recv(1024) recv_content = recv_data.decode("gbk") print(f"客户端:{recv_content},来自:{client_info}")

进入一个无限循环,每次接收客户端发送的数据,并将其解码成字符串。然后打印客户端的信息和接收到的内容。

if recv_content == "图片": filepath = "003.jpg" fhead = struct.pack(b'128sq', bytes(os.path.basename(filepath), encoding='utf-8'), os.stat(filepath).st_size) client_socket.send(fhead) fp = open(filepath, 'rb') while True: data = fp.read(1024) if not data: print('{0} send over ....'.format(filepath)) break client_socket.send(data)

如果接收到的内容是 "图片",则发送指定的图片文件给客户端。首先,打包文件名和文件大小为一个固定大小的字节流,并使用 client_socket.send() 方法将其发送给客户端。然后,打开要发送的图片文件,并进入一个循环,每次读取 1024 字节的数据并发送给客户端,直到文件读取完毕。

 

elif recv_content == "end": client_socket.send("end".encode('gbk')) print("结束接收信息!") break

如果接收到的内容是 "end",则发送 "end" 给客户端,表示结束接收信息,并退出循环。

 

else: client_socket.send("你好,我是菜狗!".encode('gbk'))

对于其他接收到的内容,发送一个固定的回复消息给客户端。

 

def handler(server_socket): while True: client_socket, client_info = server_socket.accept() t1 = Thread(target=recv_data, args=(client_socket, client_info)) t1.start() t1.join()

定义了一个名为 handler 的函数,用于处理客户端连接和线程的操作。进入一个无限循环,使用 server_socket.accept() 方法接受客户端的连接请求,获得客户端套接字对象和客户端信息。然后创建一个线程,调用 recv_data 函数处理客户端的数据,并启动线程。最后,等待线程执行完毕。

 

if __name__ == '__main__': server_socket = socket(AF_INET, SOCK_STREAM) server_socket.bind(('192.168.10.156', 8885)) server_socket.listen(5) print("等待连接!") handler(server_socket) server_socket.close()

如果当前脚本是作为主程序运行,则创建一个 TCP/IP 的套接字对象 server_socket,绑定指定的服务器地址和端口号,然后调用 handler 函数处理客户端连接和线程。最后,关闭服务器套接字。

import os
import struct
from socket import *
from threading import Thread

导入了需要使用的模块,包括 osstructsocketthreading

 

def deal_image(sock): while True: fileinfo_size = struct.calcsize("128sq") buf = sock.recv(fileinfo_size) # 接收图片名 if buf: filename, filesize = struct.unpack("128sq", buf) fn = filename.decode().strip("\x00") new_filename = os.path.join("./", "client_" + fn) recvd_size = 0 fp = open(new_filename, "wb") while not recvd_size == filesize: if filesize - recvd_size > 1024: data = sock.recv(1024) recvd_size += len(data) else: data = sock.recv(1024) recvd_size = filesize fp.write(data) # 写入图片数据 print("write over...") fp.close() sock.close() break

定义了一个名为 deal_image 的函数,用于处理接收图片文件的操作。进入一个无限循环,首先通过 struct.calcsize() 方法计算要接收的数据的大小。然后使用 sock.recv() 方法接收图片名,并使用 struct.unpack() 方法解包得到图片名和文件大小。接着根据接收到的图片名创建新的文件名,并以二进制写模式打开文件。接下来进入一个循环,每次接收 1024 字节的数据,并将其写入文件,直到文件的大小与已接收的数据大小相等。最后关闭文件和套接字,并退出循环。

 

def send_data(): while True: msg = input(">") client_socket.send(msg.encode("gbk")) deal_image(client_socket) if msg == "end": print("结束发送消息") break

定义了一个名为 send_data 的函数,用于处理发送数据的操作。进入一个无限循环,首先通过 input() 方法获取用户输入的消息。然后使用 client_socket.send() 方法将消息编码为指定的字符集并发送给服务端。接着调用 deal_image() 函数处理接收图片文件的操作。如果用户输入的消息是 "end",则打印结束发送消息的提示,并退出循环。

 

if __name__ == '__main__': client_socket = socket(AF_INET, SOCK_STREAM) client_socket.connect(("192.168.10.156", 8885)) t2 = Thread(target=send_data) t2.start() t2.join() client_socket.close()

如果当前脚本是作为主程序运行,则创建一个 TCP/IP 的套接字对象 client_socket,并使用 client_socket.connect() 方法连接指定的服务器地址和端口号。然后创建一个线程,调用 send_data 函数处理发送数据的操作,并启动线程。最后,等待线程执行完毕,关闭客户端套接字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值