Python中的socket模块提供了底层的网络接口,使用Python的socket模块可以实现网络上不同计算机之间的socket通信。Python中的socket实现了BSD(Berkeley Software Distribution)套接字标准。
创建一个socket对象,然后即可使用socket对象的方法创建连接。socket()函数的原型如下。
socket( family, type, proto)
其参数含义如下。
可以使用socket对象的bind方法绑定IP地址和端口。bind方法的原型如下。
bind(address)
其参数含义如下。
使用socket对象的listen方法可以监听由socket对象创建的连接。其函数原型如下。
listen(backlog)
使用socket对象的connect和connect_ex都可以连接到服务端,不同的是,当连接不成功时,connect将返回一个错误,而connect_ex则引发一个异常。其函数原型如下。
connect(address)
connect_ex(address)
其参数含义相同,如下所示。
使用socket对象的accept方法可以接受来自客户端的连接,accept方法将返回一个新的socket对象和客户端的地址。使用socket对象的recv和recvfrom方法都可以从socket对象获取数据,不同的是,recvfrom方法返回所接受的字符串和地址,而recv方法仅返回字符串,其原型如下。
recv(bufsize, flags)
recvfrom(bufsize, flags)
其参数含义相同,如下所示。
使用socket对象的send和sendall方法都可以向已经连接的socket发送数据,不同的是,sendall将一次发送完全部数据。其原型如下。
send(string, flags)
sendall(string, flags)
其参数含义相同,如下所示。
使用socket对象的sendto方法可以向一个未连接的socket发送数据,其参数原型如下。
sendto(string, flags, address)
其参数含义如下。
使用socket对象的makefile方法可以将socket关联到文件对象上,其原型如下。
makefile(mode, bufsize)
其参数含义如下。
当完成通信后,应使用socket对象的close方法关闭网络连接。
#-*- coding:utf-8 -*-
#file: server.py
#
import tkinter
import threading
import socket
classListenThread(threading.Thread):# 监听线程
def__init__(self,edit,server):
threading.Thread.__init__(self)
self.edit = edit # 保存窗口中的多行文本框
self.server = server
defrun(self):# 进入监听状态
while1: # 使用while循环等待连接
try: # 捕获异常
client, addr = self.server.accept() # 等待连接
self.edit.insert(tkinter.END, # 向文本框中输出状态
'连接来自:%s:%d\n' % addr)
data = client.recv(1024) # 接收数据
self.edit.insert(tkinter.END, # 向文本框中输出数据
'收到数据:%s \n' % data)
client.send(str('I GOT: %s' % data).encode()) # 发送数据
client.close() # 关闭同客户端的连接
self.edit.insert(tkinter.END, # 向文本框中输出状态
'关闭客户端\n')
except: # 异常处理
self.edit.insert(tkinter.END, # 向文本框中输出状态
'关闭连接\n')
break# 结束循环
classControl(threading.Thread):# 控制线程
def__init__(self, edit):
threading.Thread.__init__(self)
self.edit = edit # 保存窗口中的多行文本框
self.event = threading.Event() # 创建Event对象
self.event.clear() # 清除event标志
defrun(self):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建socket连接
server.bind(('', 1051)) # 绑定本机1051端口
server.listen(1) # 开始监听
self.edit.insert(tkinter.END,'正在等待连接\n') # 向文本框中输出状态
self.lt = ListenThread(self.edit,server) # 创建监听线程对象
self.lt.setDaemon(True)
self.lt.start() # 执行监听线程
self.event.wait() # 进入等待状态
server.close() # 关闭连接
defstop(self):# 结束控制进程
self.event.set() # 设置event标志
classWindow:# 主窗口
def__init__(self, root):
self.root = root
self.butlisten = tkinter.Button(root, # 创建组件
text = '开始监听', command = self.Listen)
self.butlisten.place(x = 20, y = 15)
self.butclose = tkinter.Button(root,
text = '停止监听', command = self.Close)
self.butclose.place(x = 120, y = 15)
self.edit = tkinter.Text(root)
self.edit.place(y = 50)
defListen(self):# 处理按钮事件
self.ctrl = Control(self.edit) # 创建控制线程对象
self.ctrl.setDaemon(True)
self.ctrl.start() # 执行控制线程
defClose(self):
self.ctrl.stop() # 结束控制线程
root = tkinter.Tk()
window = Window(root)
root.mainloop()
#-*- coding:utf-8 -*-
#file: client.py
#
import tkinter
import socket
classWindow:
def__init__(self, root):# 创建组件
label1 = tkinter.Label(root, text = 'IP')
label2 = tkinter.Label(root, text = 'Port')
label3 = tkinter.Label(root, text = 'Data')
label1.place(x = 5, y = 5)
label2.place(x = 5, y = 30)
label3.place(x = 5, y = 55)
self.entryIP = tkinter.Entry(root)
self.entryIP.insert(tkinter.END, '127.0.0.1')
self.entryPort = tkinter.Entry(root)
self.entryPort.insert(tkinter.END, '1051')
self.entryData = tkinter.Entry(root)
self.entryData.insert(tkinter.END, 'Hello')
self.Recv = tkinter.Text(root)
self.entryIP.place(x = 40, y = 5)
self.entryPort.place(x = 40, y = 30)
self.entryData.place(x = 40, y = 55)
self.Recv.place(y = 115)
self.send = tkinter.Button(root, text = '发送数据', command = self.Send)
self.send.place(x = 40, y = 80)
defSend(self):# 按钮事件
try: # 异常处理
ip = self.entryIP.get() # 获取IP
port = int(self.entryPort.get()) # 获取端口
data = self.entryData.get() # 获取发送数据
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建socket对象
client.connect((ip,port)) # 连接服务端
client.send(data) # 发送数据
rdata = client.recv(1024) # 结束数据
self.Recv.insert(tkinter.END, 'Server:' + rdata .decode() + '\n') # 输出接受的数据
client.close() # 关闭连接
except :
self.Recv.insert(tkinter.END, '发送错误\n')
root = tkinter.Tk()
window = Window(root)
root.mainloop()
#-*- coding:utf-8 -*-
#file: FileServer.py
#
import tkinter
import threading
import socket
import os
classListenThread(threading.Thread):# 创建监听线程
def__init__(self,edit,server):
threading.Thread.__init__(self)
self.edit = edit # 保存窗口中的多行文本框
self.server = server
self.file = 'receive.txt'
defrun(self):# 进入监听状态
while1: # 使用while循环不停监听
try: # 捕获异常
self.client, addr = self.server.accept() # 等待连接
self.edit.insert(tkinter.END, # 向文本框中输出状态
'连接来自:%s:%d\n' % addr)
self.edit.insert(tkinter.END, # 向文本框中输出数据
'开始接收数据:')
file = os.open(self.file, os.O_WRONLY|os.O_CREAT # 创建文件
|os.O_EXCL|os.O_BINARY)
while1:
rdata = self.client.recv(1024) # 接受数据
ifnot rdata:
break
os.write(file,rdata) # 将数据写入文件
self.edit.insert(tkinter.END,'......') # 向文本框中输出进度
os.close(file) # 关闭文件
self.client.close() # 关闭与客户端的连接
self.edit.insert(tkinter.END, # 向文本框中输出状态
'\n接收完毕,关闭客户端\n')
except: # 异常处理
self.edit.insert(tkinter.END, # 向文本框中输出状态
'\n网络错误,关闭连接\n')
break# 结束循环
classControl(threading.Thread):# 控制线程
def__init__(self, edit):
threading.Thread.__init__(self)
self.edit = edit # 保存窗口中的多行文本框
self.event = threading.Event() # 创建Event对象
self.event.clear() # 清除event标志
defrun(self):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建socket连接
server.bind(('', 1051)) # 绑定本机1051端口
server.listen(1) # 开始监听
self.edit.insert(tkinter.END,'正在等待连接\n') # 向文本框中输出状态
self.lt = ListenThread(self.edit,server) # 创建监听线程对象
self.lt.setDaemon(True)
self.lt.start() # 执行监听线程
self.event.wait() # 进入等待状态
server.close() # 关闭连接
defstop(self):# 结束控制进程
self.event.set() # 设置event标志
classWindow:# 主窗口
def__init__(self, root):
self.root = root
self.butlisten = tkinter.Button(root, # 创建组件
text = '开始监听', command = self.Listen)
self.butlisten.place(x = 20, y = 15)
self.butclose = tkinter.Button(root,
text = '停止监听', command = self.Close)
self.butclose.place(x = 120, y = 15)
self.edit = tkinter.Text(root)
self.edit.place(y = 50)
defListen(self):# 处理按钮事件
self.ctrl = Control(self.edit) # 创建控制线程对象
self.ctrl.setDaemon(True)
self.ctrl.start() # 执行控制线程
defClose(self):
self.ctrl.stop() # 结束控制线程
root = tkinter.Tk()
window = Window(root)
root.mainloop()
#-*- coding:utf-8 -*-
#file: FileClient.py
#
import tkinter
import tkinter.filedialog
import socket
import os
classWindow:
def__init__(self, root):# 创建组件
label1 = tkinter.Label(root, text = 'IP')
label2 = tkinter.Label(root, text = 'Port')
label3 = tkinter.Label(root, text = '文件')
label1.place(x = 5, y = 5)
label2.place(x = 5, y = 30)
label3.place(x = 5, y = 55)
self.entryIP = tkinter.Entry(root)
self.entryIP.insert(tkinter.END, '127.0.0.1')
self.entryPort = tkinter.Entry(root)
self.entryPort.insert(tkinter.END, '1051')
self.entryData = tkinter.Entry(root)
self.entryData.insert(tkinter.END, 'Hello')
self.entryIP.place(x = 40, y = 5)
self.entryPort.place(x = 40, y = 30)
self.entryData.place(x = 40, y = 55)
self.send = tkinter.Button(root, text = '发送文件', command = self.Send)
self.openfile = tkinter.Button(root, text = '浏览', command = self.Openfile)
self.send.place(x = 40, y = 80)
self.openfile.place( x = 170, y = 55)
defSend(self):# 按钮事件
try: # 异常处理
ip = self.entryIP.get() # 获取IP
port = int(self.entryPort.get()) # 获取端口
filename = self.entryData.get() # 获取发送数据
tt = filename.split('/')
name = tt[len(tt)-1]
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建socket对象
client.connect((ip,port)) # 连接服务端
client.send(name.encode()) # 发送文件名
file = os.open(filename, os.O_RDONLY | os.O_EXCL|os.O_BINARY) # 打开文件
while1: # 发送文件
data = os.read(file,1024)
ifnot data:
break
client.send(data)
os.close(file) # 关闭文件
client.close() # 关闭连接
except Exception as e :
print('发送错误',e)
defOpenfile(self):
r = tkinter.filedialog.askopenfilename(title = 'Python tkinter', # 创建打开文件对话框
filetypes=[('All files', '*'),('Python', '*.py *.pyw')])
if r:
self.entryData.delete(0, tkinter.END)
self.entryData.insert(tkinter.END, r)
root = tkinter.Tk()
window = Window(root)
root.mainloop()