• Pyton学习(5)--socket编程,一个简单的对话框


    这次学习涉及以下几个问题:

    1,同时运行两个python程序的方法

    2,socket编程初探

    3,多线程编程初探

    4,GUI编程tix部分控件的属性

    5,Python的list类型

    1、同时运行两个程序的方法

    有这个问题的原因是:socket编程,通常是两个程序进行试验,server和client。之前搞了好长时间,使用vscode调试的时候发现一个IDE只能运行一个程序。

    问题解决也很简单:开两个vscode。。。

    2、socket编程

    socket最基本的编程模型:Server-Client模型(TCP链接)。 

    2.1 基本模型

    2.2 服务端代码

    1. #!/usr/bin/python
    2. # -*- coding: UTF-8 -*-
    3. # 文件名:server.py
    4. import socket # 导入 socket 模块
    5. import sys
    6. s = socket.socket() # 创建 socket 对象
    7. host = socket.gethostname() # 获取本地主机名
    8. port = 33222 # 设置端口
    9. s.bind((host, port)) # 绑定端口
    10. s.listen(5) # 等待客户端连接
    11. while True:
    12. conn, addr = s.accept() # 建立客户端连接
    13. print(conn)
    14. print(addr)
    15. recvbuff = conn.recv(1024).decode()
    16. print(recvbuff)
    17. sendbuf = '已经链接'
    18. conn.send(sendbuf.encode())
    19. s.close() # 关闭连接
    20. conn.close()
    21. sys.exit()

    2.3 客户端代码

    1. #!/usr/bin/python
    2. # -*- coding: UTF-8 -*-
    3. # 文件名:client.py
    4. import socket # 导入 socket 模块
    5. c = socket.socket() # 创建 socket 对象
    6. host = socket.gethostname() # 获取本地主机名
    7. port = 33222 # 设置端口号
    8. c.connect((host, port))
    9. c.send('我是土豆!'.encode());
    10. print(c.recv(1024).decode())
    11. c.close()

    2.4 运行结果

    服务端:

    客户端:

    3、多线程编程

    由于本次练习的程序需要GUI窗口和socket编程两个过程(模块)。以我的知识,为了不让两个过程冲突,我认为需要使用多线程编程。

    1. 第一个是主程序:窗口及其控件的处理
    2. 第二个是线程:   socket数据收发的处理

    调用thread模块中的start_new_thread()函数来产生新线程。语法如下:

    thread.start_new_thread ( function, args[, kwargs] )

    参数说明:

    • function - 线程函数。
    • args - 传递给线程函数的参数,他必须是个tuple类型。
    • kwargs - 可选参数。

    4、控件属性

    由于要对对话框进行简单的设置,我这次需要用到以下几个控件属性

    justify

    定义对齐方式,可选值有:LEFT,RIGHT,CENTER,默认为 CENTER。

    relief

    边框样式,可选的有:FLAT、SUNKEN、RAISED、GROOVE、RIDGE。默认为 FLAT。

    width

    设置标签宽度,默认值是 0,自动计算,单位以像素计。

    height

    标签的高度,默认值是 0。

    5、list对象

    作为Server端接收方,要在Lable上显示从Client收到的数据,而且是积累数据。有几种方法:

    1. Lable能自己记住历史数据;
    2. 自己写一个类似于链表的东西记录历史数据;
    3. 面向对象的语言一般都有自己成熟的类似链表的类;

    本次是学习,所以就找了下Python是否有自己成熟的类或者对象,List符合要求

    序列(List)是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。

    Python有6个序列的内置类型,但最常见的是列表和元组。

    创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。如下所示:

    1. list1 = ['physics', 'chemistry', 1997, 2000]
    2. list2 = [1, 2, 3, 4, 5 ]
    3. list3 = ["a", "b", "c", "d"]

    这个东西基本可以使用:先把Server每次从Client收到的数据存到List,显示的时候顺序打出来,放到Lable的text框中

    6、一个socket对话框的代码示例

    服务端代码:

    1. #!/usr/bin/python
    2. # -*- coding: UTF-8 -*-
    3. # 文件名:server.py
    4. import _thread
    5. from tkinter import GROOVE, RAISED, RIDGE, SUNKEN, LEFT, StringVar, tix
    6. import socket # 导入 socket 模块
    7. import sys
    8. recvbuff = 'hello world! \n你好,世界'
    9. listbuff = []
    10. conn = socket.socket()
    11. def recvfun():
    12. s = socket.socket() # 创建 socket 对象
    13. host = socket.gethostname() # 获取本地主机名
    14. port = 33222 # 设置端口
    15. s.bind((host, port)) # 绑定端口
    16. s.listen(5) # 等待客户端连接
    17. global conn
    18. global listbuff
    19. conn, addr = s.accept() # 建立客户端连接
    20. while True:
    21. l_test_buff = ''
    22. recvbuff = conn.recv(1024).decode()
    23. recvbuff = str(addr)+':'+recvbuff+'\n'
    24. listbuff.append(recvbuff)
    25. for recb1 in listbuff:
    26. l_test_buff = l_test_buff + recb1
    27. l_text.set(l_test_buff)
    28. return
    29. #创建线程处理收到的消息
    30. _thread.start_new_thread(recvfun)
    31. #def windows_init():
    32. mywin = tix.Tk()
    33. mywin.title("socket window Server")
    34. #定义StringVar
    35. l_text = StringVar()
    36. l_text.set(recvbuff)
    37. #初始化数据
    38. text = "hello world! \n你好,世界"
    39. l_text.set(text)
    40. #button2 myclean实现 清除Entry内容,并回复成原状
    41. def myclearn():
    42. text = "hello world! \n你好,世界"
    43. l_text.set(text)
    44. e_00.delete(0, "end")
    45. return
    46. #FLAT、SUNKEN、RAISED、GROOVE、RIDGE
    47. #l_00 = tix.Label(root, font=("微软雅黑", 12), width=40, height=10, relief=SUNKEN, bg='#FFFFFF') .set(recvbuff)
    48. #justify 定义对齐方式,可选值有:LEFT,RIGHT,CENTER,默认为 CENTER。
    49. l_00 = tix.Label(mywin, font=("微软雅黑", 12), relief=SUNKEN, justify=LEFT, width=40, height=10, textvariable=l_text)
    50. l_00.pack(pady=20)
    51. e_00 = tix.Entry(mywin, font=("微软雅黑", 12))
    52. e_00.pack(pady=20)
    53. #服务端暂时没用
    54. def sendmsg():
    55. text = e_00.get()
    56. #l_text.set(text)
    57. conn.send(text.encode())
    58. return
    59. b1 = tix.Button(mywin, text="发送", command=sendmsg)
    60. b1.pack(pady=10, side='left')
    61. b2 = tix.Button(mywin, text="清空", command=myclearn)
    62. b2.pack(before=b1, side='left', padx=70, pady=10)
    63. # 进入消息循环
    64. mywin.mainloop()
    65. #return
    66. #窗口
    67. #_thread.start_new_thread(windows_init)
    68. #windows_init()

    客户端代码:

    1. #!/usr/bin/python
    2. # -*- coding: UTF-8 -*-
    3. # 文件名:server.py
    4. import _thread
    5. from tkinter import GROOVE, RAISED, RIDGE, SUNKEN, StringVar, tix
    6. import socket # 导入 socket 模块
    7. import sys
    8. recvbuff = 'hello world! \n你好,世界'
    9. def recvfun():
    10. s = socket.socket() # 创建 socket 对象
    11. host = socket.gethostname() # 获取本地主机名
    12. port = 33222 # 设置端口
    13. s.bind((host, port)) # 绑定端口
    14. s.listen(5) # 等待客户端连接
    15. while True:
    16. conn, addr = s.accept() # 建立客户端连接
    17. recvbuff = conn.recv(1024).decode()
    18. recvbuff = str(addr)+':'+recvbuff
    19. l_text.set(recvbuff)
    20. #print(recvbuff)#
    21. sendbuf = '已经连接!'
    22. conn.send(sendbuf.encode())
    23. return
    24. #_thread.start_new_thread(recvfun)
    25. #def windows_init():
    26. mywin = tix.Tk()
    27. mywin.title("socket window Client")
    28. #定义StringVar
    29. l_text = StringVar()
    30. l_text.set(recvbuff)
    31. #初始化数据
    32. text = "hello world! \n你好,世界"
    33. l_text.set(text)
    34. c = socket.socket() # 创建 socket 对象
    35. host = socket.gethostname() # 获取本地主机名
    36. port = 33222 # 设置端口号
    37. c.connect((host, port))
    38. #button2 myclean实现 清除Entry内容,并回复成原状
    39. def myclearn():
    40. text = "hello world! \n你好,世界"
    41. l_text.set(text)
    42. e_00.delete(0, "end")
    43. global c
    44. c.close()
    45. return
    46. #FLAT、SUNKEN、RAISED、GROOVE、RIDGE
    47. #l_00 = tix.Label(root, font=("微软雅黑", 12), width=40, height=10, relief=SUNKEN, bg='#FFFFFF') .set(recvbuff)
    48. l_00 = tix.Label(mywin, font=("微软雅黑", 12), relief=SUNKEN, width=40, height=10, textvariable=l_text)
    49. l_00.pack(pady=20)
    50. e_00 = tix.Entry(mywin, font=("微软雅黑", 12))
    51. e_00.pack(pady=20)
    52. def sendmsg():
    53. global c
    54. text = e_00.get()
    55. c.send(text.encode());
    56. return
    57. b1 = tix.Button(mywin, text="发送", command=sendmsg)
    58. b1.pack(pady=10, side='left')
    59. b2 = tix.Button(mywin, text="清空", command=myclearn)
    60. b2.pack(before=b1, side='left', padx=70, pady=10)
    61. # 进入消息循环
    62. mywin.mainloop()
    63. #return
    64. #窗口
    65. #_thread.start_new_thread(windows_init)
    66. #windows_init()

    运行结果:

    左边Server,右边Client

  • 相关阅读:
    算法学习笔记(29):分块
    创建Vue项目的常用npm插件总结
    优秀软件测试报告
    【T3】畅捷通T3备份账套提示:超时已过期,错误‘53‘文件不存在。
    Java I/O 的 OutputStream 输出流相关知识点详解
    使用@Constraint和自定义注解校验接口入参
    URP渲染管线场景优化实战 2.3静态资源导入及优化——Texture
    Java常见设计模式总结
    腾讯核心人员纯手写出这份JAVA面试全集总结,简直不要太香了!
    Python的简单使用与应用
  • 原文地址:https://blog.csdn.net/monkeyzh123/article/details/126096707