配置教程闲时补充!
server源码
import socket
host = '192.168.43.241'
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
sock, addr = s.accept()
print('Connection built')
info = sock.recv(1024).decode()
while info != 'exit':
print('client:' + info)
send_mes = input()
sock.send(send_mes.encode())
if send_mes == 'exit':
break
info = sock.recv(1024).decode()
sock.close()
s.close()
在另一台电脑重复上述创建Client;由于我单笔记本操作,直接用python3的IDLE创建的Client端:
client源码
import socket
s= socket.socket()
host = '192.168.43.241'
port = 12345
s.connect((host,port))
print('Linked')
info = ''
while info != 'exit':
print('Server:'+info)
send_mes=input()
s.send(send_mes.encode())
if send_mes =='exit':
break
info = s.recv(1024).decode()
s.close()
先运行server端再运行client端:
环境:eclipse+wxFrombuilder
(1)安装wxFormBuilder
安装wxFormBuilder(安装教程点这儿~)
(2)wxFromBuilder创建clientUI
我的server端未设置界面
Python界面生成器wxFormBuilder简单使用入门教程(入门教程点这儿~)
- 打开wxFormBuilder创建窗体Froms
- 加入布局layout:点几次生成几个,重复点呈阶梯状创建
- 我们需要在一个layout下创建平行的3个layout:点击bSizer2,再点击layout的bSizer5,再点击bSizer2,创建layout的bSizer6,7
这样为同一层的布局:
- 点击wxBoxSizer->选择common下的布局创建label、textCtrl、button呈竖排列:
- 选中wxBoxSizer,点击右边orient排列的wxHORIZONTAL横向排列:
- 上方有对其方式和快捷放大:
- Proprotion也可以改变bSizer的所占比例:
- 默认wx.style不支持换行,建议勾选上wxTE_MULTLINE:
- 我的Client示例界面:
(二)wxpython库文件安装配置
(1)下载wxpython库
pip install wxPython
如果命令不在,还得
安装pip
模块(我的环境为python3.7,自带pip)
import wx # 导入wx包
app = wx.App() # 创建应用程序对象
win = wx.Frame(None, -1, 'Python') # 创建窗体
win.Show() # 显示窗体
app.MainLoop() # 运行程序
打开PyDev->Interpreters->Python Interpreter->找到Libraries栏->新建一个文件夹new Folder(找到之前创建的文件夹wxform的路径)->应用Apply and Close
clientframe.py
这是引入界面程序,贴这儿方便以后创建其他界面引入;具体的TCP聊天界面源码后面给出~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
u'''
Created on 2018年12月7日
@author: CUNGU
'''
__author__ = 'cungudafa'
__version__ = '1.0.0'
__company__ = u'重庆交大'
__updated__ = '2018-12-09'
import wx
import noname
class CliFrame(noname.MyFrame1):
def __init__(self, parent):
noname.MyFrame1.__init__(self, parent)
def main():
app = wx.App(False)
frame = CliFrame(None)
frame.Show(True)
app.MainLoop()
if __name__ == "__main__":
main()
pass
运行:
5. 若要再在wxformBuider修改界面(保存,F8获得一个新的 noname.py),只要不移动之前引入wxform包的位置,只需将新生成noname.py拖来替换eclipse中相应位置即可。(若有键名改变,则要修改clientframe中的键字名。)
clientframe.py
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
u'''
Created on 2018年12月7日
@author: CUNGU
'''
__author__ = 'cungudafa'
__version__ = '1.0.0'
__company__ = u'重庆交大'
__updated__ = '2018-12-10'
import wx
import noname
from socket import *
s = socket(AF_INET, SOCK_STREAM)
class ClientFrame(noname.MyFrame1):
def __init__(self, parent):
noname.MyFrame1.__init__(self, parent)
def btn_login(self, event):
address = self.ip_text.GetValue() # 服务器的ip地址
port = int(self.port_text.GetValue()) # 服务器的端口号
s.connect((address, port))
def btn_send(self, event): # 发送消息
buffsize = 1024 # 接收数据的缓存大小
senddata = self.sendmessage.GetValue() # 获得输入栏的内容
s.send(senddata.encode()) # 发送消息
recvdata = s.recv(buffsize).decode('utf-8') # 接收消息,格式转换
self.showmessage.AppendText('\n' + recvdata)
self.sendmessage.SetValue("") # 清空输入栏
def btn_out(self, event):
self.Close(True) # 关闭窗口
def main():
app = wx.App(False)
frame = ClientFrame(None)
frame.Show(True)
# 启动窗口
app.MainLoop()
if __name__ == "__main__":
try:
main()
finally:
s.close()
无界面的_init _.py
# 服务器
# -*- encoding: utf-8 -*-
import socket
import threading
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_set = set() # 用来保存每个socket对象
s.bind(('127.0.0.1', 12345)) # 绑定地址和端口
s.listen(5)
print('server is waiting connect.....')
def tcplink(sock, addr):
host1, port1 = addr
print('[%s:%s] is online...' % addr)
while True:
try:
data = sock.recv(1024).decode('utf-8')
print('Client say:' + data)
senddata = "port " + str(port1) + ": " + data # 收到的信息进行处理
sock.send(senddata.encode()) # 将收到的信息返回给客户端
except:
socket_set.remove(sock)
print('[%s:%s] is down!' % addr)
break
if data == 'exit' or not data:
socket_set.remove(sock)
sock.close()
print('[%s:%s] is down!' % addr)
break
else:
list1 = []
for i in socket_set:
if i != sock:
list1.append(i)
for i in list1:
i.send(data)
while True:
# 接受一个客户端连接
sock, addr = s.accept() # addr是个元组('127.0.0.1',端口)
socket_set.add(sock) # 把socket对象添加到集合中
# 创建新线程来处理TCP连接
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()
# -*- coding: utf-8 -*-
###########################################################################
## Python code generated with wxFormBuilder (version Jan 23 2018)
## http://www.wxformbuilder.org/
##
## PLEASE DO *NOT* EDIT THIS FILE!
###########################################################################
import wx
import wx.xrc
###########################################################################
## Class MyFrame1
###########################################################################
class MyFrame1 ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 472,466 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
bSizer2 = wx.BoxSizer( wx.VERTICAL )
bSizer8 = wx.BoxSizer( wx.HORIZONTAL )
self.m_staticText1 = wx.StaticText( self, wx.ID_ANY, u"IP:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText1.Wrap( -1 )
bSizer8.Add( self.m_staticText1, 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.BOTTOM|wx.LEFT, 5 )
self.ip_text = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer8.Add( self.ip_text, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticText3 = wx.StaticText( self, wx.ID_ANY, u" Port:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText3.Wrap( -1 )
bSizer8.Add( self.m_staticText3, 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.BOTTOM|wx.LEFT, 5 )
self.port_text = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer8.Add( self.port_text, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
self.enter_btn = wx.Button( self, wx.ID_ANY, u"进入", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer8.Add( self.enter_btn, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer2.Add( bSizer8, 1, wx.EXPAND, 5 )
bSizer1.Add( bSizer2, 1, wx.EXPAND, 5 )
bSizer3 = wx.BoxSizer( wx.VERTICAL )
self.showmessage = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE )
bSizer3.Add( self.showmessage, 1, wx.ALL|wx.EXPAND, 5 )
bSizer1.Add( bSizer3, 5, wx.EXPAND, 5 )
bSizer4 = wx.BoxSizer( wx.HORIZONTAL )
bSizer5 = wx.BoxSizer( wx.VERTICAL )
self.sendmessage = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer5.Add( self.sendmessage, 1, wx.ALL|wx.EXPAND, 5 )
bSizer4.Add( bSizer5, 6, wx.EXPAND, 5 )
bSizer7 = wx.BoxSizer( wx.VERTICAL )
self.send_btn = wx.Button( self, wx.ID_ANY, u"发送", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer7.Add( self.send_btn, 5, wx.ALL|wx.ALIGN_RIGHT, 5 )
self.exit_btn = wx.Button( self, wx.ID_ANY, u"退出", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer7.Add( self.exit_btn, 5, wx.ALL, 5 )
bSizer4.Add( bSizer7, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer1.Add( bSizer4, 2, wx.EXPAND, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.enter_btn.Bind( wx.EVT_BUTTON, self.btn_login )
self.send_btn.Bind( wx.EVT_BUTTON, self.btn_send )
self.exit_btn.Bind( wx.EVT_BUTTON, self.btn_out )
def __del__( self ):
pass
# Virtual event handlers, overide them in your derived class
def btn_login( self, event ):
event.Skip()
def btn_send( self, event ):
event.Skip()
def btn_out( self, event ):
event.Skip()
神奇发现:
eclipse支持同时运行server端、多个client端;
就不用再在IDLE上跑服务器端了,傻乎乎~
注:[1] TCP协议不支持广播,改为UDP协议则支持;
这仅是一个简单的TCP聊天参考界面~