Python通信(一)_基于socket编程_TCP通信界面

目录

  • 一、在eclipse中配置pyDev
  • 二、Tcp聊天(非图形界面)
    • (a) Server端创建
    • (b)Client端创建
    • (c)运行测试
  • 三、Tcp聊天(UI版)
    • (一)wxpython图形工具的安装、配置
    • (二)一个简单TCP客户端界面教程
      • (a)如何连接eclipse和wxpython界面
      • (b)一个简单的Tcp聊天界面(C有界面/S无界面)
      • (c)运行结果

一、在eclipse中配置pyDev

配置教程闲时补充!

二、Tcp聊天(非图形界面)

(a) Server端创建

  1. 创建PyDev Project工程:TcpClient
    Python通信(一)_基于socket编程_TCP通信界面_第1张图片
  2. 创建PyDev Package:server
    Python通信(一)_基于socket编程_TCP通信界面_第2张图片
    创建完成如下:
    Python通信(一)_基于socket编程_TCP通信界面_第3张图片

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

(b)Client端创建

在另一台电脑重复上述创建Client;由于我单笔记本操作,直接用python3的IDLE创建的Client端:

  1. 打开IDLE
  2. 创建新文件Client并保存
    Python通信(一)_基于socket编程_TCP通信界面_第4张图片
    完成创建如下:
    Python通信(一)_基于socket编程_TCP通信界面_第5张图片

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

(c)运行测试

先运行server端再运行client端:

Python通信(一)_基于socket编程_TCP通信界面_第6张图片
分析:
Python通信(一)_基于socket编程_TCP通信界面_第7张图片

三、Tcp聊天(UI版)

环境:eclipse+wxFrombuilder

(一)wxpython图形工具的安装、配置

(1)安装wxFormBuilder

安装wxFormBuilder(安装教程点这儿~)

我的参考安装记录:
Python通信(一)_基于socket编程_TCP通信界面_第8张图片
Python通信(一)_基于socket编程_TCP通信界面_第9张图片
Python通信(一)_基于socket编程_TCP通信界面_第10张图片
Python通信(一)_基于socket编程_TCP通信界面_第11张图片

(2)wxFromBuilder创建clientUI
我的server端未设置界面

Python界面生成器wxFormBuilder简单使用入门教程(入门教程点这儿~)

  1. wxFormBuilder使用方法
  • 打开wxFormBuilder创建窗体Froms
    Python通信(一)_基于socket编程_TCP通信界面_第12张图片
  • 加入布局layout:点几次生成几个,重复点呈阶梯状创建
    Python通信(一)_基于socket编程_TCP通信界面_第13张图片
  • 我们需要在一个layout下创建平行的3个layout:点击bSizer2,再点击layout的bSizer5,再点击bSizer2,创建layout的bSizer6,7
    这样为同一层的布局:
    Python通信(一)_基于socket编程_TCP通信界面_第14张图片
  • 点击wxBoxSizer->选择common下的布局创建label、textCtrl、button呈竖排列:
    Python通信(一)_基于socket编程_TCP通信界面_第15张图片
  • 选中wxBoxSizer,点击右边orient排列的wxHORIZONTAL横向排列:
    Python通信(一)_基于socket编程_TCP通信界面_第16张图片
    Python通信(一)_基于socket编程_TCP通信界面_第17张图片
  • 上方有对其方式和快捷放大:
    Python通信(一)_基于socket编程_TCP通信界面_第18张图片
  • Proprotion也可以改变bSizer的所占比例:
    Python通信(一)_基于socket编程_TCP通信界面_第19张图片
  • 默认wx.style不支持换行,建议勾选上wxTE_MULTLINE:
    Python通信(一)_基于socket编程_TCP通信界面_第20张图片
  • 我的Client示例界面:
    Python通信(一)_基于socket编程_TCP通信界面_第21张图片
  1. 保存
  • 可以修改名称
  • 导出UI为python文件:code_generation勾选Python
    Python通信(一)_基于socket编程_TCP通信界面_第22张图片
  • 保存,再按F8获取noname.py文件

建议:新建一个新的wxform文件夹(待会eclipse创建项目会引入该文件夹!)
Python通信(一)_基于socket编程_TCP通信界面_第23张图片 Python通信(一)_基于socket编程_TCP通信界面_第24张图片

  • 界面的创建就算完成了,用集成工具打开noname.py即可编辑,我们创建另一个 client.py引入noname.py就可对其编译。

(二)wxpython库文件安装配置
(1)下载wxpython库

  • 进入cmd中:
pip install wxPython

Python通信(一)_基于socket编程_TCP通信界面_第25张图片

如果命令不在,还得安装pip模块(我的环境为python3.7,自带pip)

  • 创建一个test项目进行测试wxpython是否安装成功:
import wx  # 导入wx包
app = wx.App()  # 创建应用程序对象
win = wx.Frame(None, -1, 'Python')  # 创建窗体
win.Show()  # 显示窗体
app.MainLoop()  # 运行程序

Python通信(一)_基于socket编程_TCP通信界面_第26张图片
(2)为eclipse-PyDev引入wxform文件夹

  • 打开eclipse->Windows选择Preference(属性)
    Python通信(一)_基于socket编程_TCP通信界面_第27张图片

  • 打开PyDev->Interpreters->Python Interpreter->找到Libraries栏->新建一个文件夹new Folder(找到之前创建的文件夹wxform的路径)->应用Apply and Close

Python通信(一)_基于socket编程_TCP通信界面_第28张图片

(二)一个简单TCP客户端界面教程

(a)如何连接eclipse和wxpython界面

  1. 创建PyDev Project,命名为TcpChatUI
    Python通信(一)_基于socket编程_TCP通信界面_第29张图片
  2. 在src下新建一个PyDev Package,命名为client
    Python通信(一)_基于socket编程_TCP通信界面_第30张图片
  3. noname.py文件直接拖进client包中
    Python通信(一)_基于socket编程_TCP通信界面_第31张图片
    noname.py文件如下:
    Python通信(一)_基于socket编程_TCP通信界面_第32张图片
  4. 我们在noname.py同目录下新建一个clientframe.py的文件,用’‘import noname’'继承frame界面,再对noname.py布局的函数进行代码重写
    Python通信(一)_基于socket编程_TCP通信界面_第33张图片

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

运行:
Python通信(一)_基于socket编程_TCP通信界面_第34张图片
5. 若要再在wxformBuider修改界面(保存,F8获得一个新的 noname.py),只要不移动之前引入wxform包的位置,只需将新生成noname.py拖来替换eclipse中相应位置即可。(若有键名改变,则要修改clientframe中的键字名。)
Python通信(一)_基于socket编程_TCP通信界面_第35张图片

(b)一个简单的Tcp聊天界面(C有界面/S无界面)

  1. 思路见代码注释,我的project如下:
    Python通信(一)_基于socket编程_TCP通信界面_第36张图片
  2. client端:基于tcp协议传输(C/S双方建立连接,对连接要求高,三次握手,受保护(仅支持双方通信));扩展:如果是基于UDP协议通信,那是面向无连接,支持广播,即可以疯狂聊天模式。

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()
  1. server端

无界面的_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()

  1. 贴出我的参考 noname.py 如下:
# -*- 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()

(c)运行结果

神奇发现:
eclipse支持同时运行server端、多个client端;
就不用再在IDLE上跑服务器端了,傻乎乎~

  • 先运行服务器端(_ init.py _),再运行客户端(clientframe.py),如图:
    Python通信(一)_基于socket编程_TCP通信界面_第37张图片
  • 输入 本机ip:(127.0.0.1)端口号:(12345)由于服务器端无界面,我设为固定端口;
    Python通信(一)_基于socket编程_TCP通信界面_第38张图片
  • 多线程支持,多次发送消息
    Python通信(一)_基于socket编程_TCP通信界面_第39张图片
  • 运行第2个客户端
    Python通信(一)_基于socket编程_TCP通信界面_第40张图片

注:[1] TCP协议不支持广播,改为UDP协议则支持;
这仅是一个简单的TCP聊天参考界面~

你可能感兴趣的:(Python,Python学习)