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

本文介绍了如何使用Python进行socket编程,包括Server-Client模型的基本实现,以及如何通过多线程处理GUI与socket数据收发,避免两者冲突。同时,展示了使用Tkinter的tix库创建GUI对话框,并利用List存储和展示历史数据。最后,给出了一个包含服务器和客户端的完整socket对话框代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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 服务端代码

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 文件名:server.py
import socket            # 导入 socket 模块
import sys      
s = socket.socket()          # 创建 socket 对象
host = socket.gethostname()  # 获取本地主机名
port = 33222                # 设置端口
s.bind((host, port))        # 绑定端口

s.listen(5)                 # 等待客户端连接
while True:
    conn, addr = s.accept()     # 建立客户端连接
    print(conn)
    print(addr)
    recvbuff = conn.recv(1024).decode()
    print(recvbuff)
    sendbuf = '已经链接'
    conn.send(sendbuf.encode())

s.close()                # 关闭连接
conn.close()
sys.exit()

2.3 客户端代码

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 文件名:client.py
 
import socket               # 导入 socket 模块
 
c = socket.socket()         # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 33222                # 设置端口号
 
c.connect((host, port))
c.send('我是土豆!'.encode());
print(c.recv(1024).decode())
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个序列的内置类型,但最常见的是列表和元组。

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

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

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

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

服务端代码:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 文件名:server.py
import _thread
from tkinter import  GROOVE, RAISED, RIDGE, SUNKEN, LEFT, StringVar, tix
import socket            # 导入 socket 模块
import sys   

recvbuff = 'hello world! \n你好,世界'
listbuff = []

conn = socket.socket()    
def recvfun():
    s = socket.socket()          # 创建 socket 对象
    host = socket.gethostname()  # 获取本地主机名
    port = 33222                # 设置端口
    s.bind((host, port))        # 绑定端口
    s.listen(5)                 # 等待客户端连接
    global conn 
    global listbuff
    conn, addr = s.accept()     # 建立客户端连接
    while True:  
        l_test_buff = '' 
        recvbuff = conn.recv(1024).decode()
        recvbuff = str(addr)+':'+recvbuff+'\n'
        listbuff.append(recvbuff)
        for recb1 in listbuff:
            l_test_buff = l_test_buff + recb1
            l_text.set(l_test_buff)
    return

#创建线程处理收到的消息
_thread.start_new_thread(recvfun)

#def windows_init():
mywin = tix.Tk()
mywin.title("socket window Server")

#定义StringVar
l_text = StringVar()
l_text.set(recvbuff)
#初始化数据
text = "hello world! \n你好,世界"
l_text.set(text)

#button2 myclean实现 清除Entry内容,并回复成原状
def myclearn():
    text = "hello world! \n你好,世界"
    l_text.set(text)
    e_00.delete(0, "end")
    return

#FLAT、SUNKEN、RAISED、GROOVE、RIDGE
#l_00 = tix.Label(root, font=("微软雅黑", 12), width=40, height=10, relief=SUNKEN, bg='#FFFFFF')    .set(recvbuff)
#justify 定义对齐方式,可选值有:LEFT,RIGHT,CENTER,默认为 CENTER。
l_00 = tix.Label(mywin, font=("微软雅黑", 12), relief=SUNKEN, justify=LEFT, width=40, height=10, textvariable=l_text)
l_00.pack(pady=20)

e_00 = tix.Entry(mywin, font=("微软雅黑", 12))
e_00.pack(pady=20)

#服务端暂时没用
def sendmsg():
    text = e_00.get()
    #l_text.set(text)
    conn.send(text.encode())
    return


b1 = tix.Button(mywin, text="发送", command=sendmsg)
b1.pack(pady=10, side='left')

b2 = tix.Button(mywin, text="清空", command=myclearn)
b2.pack(before=b1, side='left', padx=70, pady=10)


# 进入消息循环
mywin.mainloop()
    #return
#窗口


#_thread.start_new_thread(windows_init)

#windows_init()


客户端代码:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 文件名:server.py
import _thread
from tkinter import  GROOVE, RAISED, RIDGE, SUNKEN, StringVar, tix
import socket            # 导入 socket 模块
import sys   


recvbuff = 'hello world! \n你好,世界'

def recvfun():
    s = socket.socket()          # 创建 socket 对象
    host = socket.gethostname()  # 获取本地主机名
    port = 33222                # 设置端口
    s.bind((host, port))        # 绑定端口
    s.listen(5)                 # 等待客户端连接
    while True:
        conn, addr = s.accept()     # 建立客户端连接
        recvbuff = conn.recv(1024).decode()
        recvbuff = str(addr)+':'+recvbuff
        l_text.set(recvbuff)
        #print(recvbuff)#
        sendbuf = '已经连接!'
        conn.send(sendbuf.encode())
    return

#_thread.start_new_thread(recvfun)

#def windows_init():
mywin = tix.Tk()
mywin.title("socket window Client")

#定义StringVar
l_text = StringVar()
l_text.set(recvbuff)
#初始化数据
text = "hello world! \n你好,世界"
l_text.set(text)

c = socket.socket()         # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 33222    # 设置端口号
c.connect((host, port))

#button2 myclean实现 清除Entry内容,并回复成原状
def myclearn():
    text = "hello world! \n你好,世界"
    l_text.set(text)
    e_00.delete(0, "end")
    global c
    c.close()
    return

#FLAT、SUNKEN、RAISED、GROOVE、RIDGE

#l_00 = tix.Label(root, font=("微软雅黑", 12), width=40, height=10, relief=SUNKEN, bg='#FFFFFF')    .set(recvbuff)


l_00 = tix.Label(mywin, font=("微软雅黑", 12), relief=SUNKEN,  width=40, height=10, textvariable=l_text)
l_00.pack(pady=20)

e_00 = tix.Entry(mywin, font=("微软雅黑", 12))
e_00.pack(pady=20)



def sendmsg():  
    global c          
    text = e_00.get()
    c.send(text.encode());
    return


b1 = tix.Button(mywin, text="发送", command=sendmsg)
b1.pack(pady=10, side='left')

b2 = tix.Button(mywin, text="清空", command=myclearn)
b2.pack(before=b1, side='left', padx=70, pady=10)


# 进入消息循环
mywin.mainloop()
    #return
#窗口


#_thread.start_new_thread(windows_init)

#windows_init()


运行结果:

左边Server,右边Client

在Python中设计一个简单的井字棋(Tic Tac Toe)游戏,你需要创建一个二维数组表示棋盘,定义游戏规则,以及处理用户输入和游戏状态检查。以下是一个基础的实现步骤: 1. **初始化棋盘**: ```python board = [[' ' for _ in range(3)] for _ in range(3)] ``` 2. **打印棋盘**: ```python def print_board(): for row in board: print('|'.join(row)) ``` 3. **获取用户输入**: ```python def get_player_move(): while True: try: row, col = map(int, input("请输入行号和列号(0-2),用逗号隔开:").split(',')) if 0 <= row < 3 and 0 <= col < 3 and board[row][col] == ' ': break else: print("无效的位置,请重新输入。") except ValueError: print("输入错误,请输入数字。") return row, col ``` 4. **放置标记**(X或O): ```python def place_mark(player): row, col = get_player_move() board[row][col] = player ``` 5. **检查胜利条件**: ```python def check_win(board, player): # 检查每一行、每一列以及两条对角线是否有三个相同的标记 for i in [0, 1, 2]: if board[i] * 3 == player * 3 or \ board[:,i] * 3 == player * 3 or \ board[(i*2)%3][(i*2)%3:i*2+3:3] * 3 == player * 3 or \ board[(i*2)%3:i*2+3:3][(i*2)%3] * 3 == player * 3: return True # 如果没有,则检查是否所有位置都有标记 if all(' ' not in row for row in board): return False return False ``` 6. **游戏循环**: ```python def play_game(): turn = 'X' while True: print_board() if check_win(board, turn): print(f"玩家{turn}获胜!") break place_mark(turn) turn = 'O' if turn == 'X' else 'X' ``` 7. **主程序**: ```python if __name__ == '__main__': play_game() ``` 这个版本的井字棋游戏是基于文本界面的,如果你想做出图形化的界面,可以使用如Pygame这样的库。完成后别忘了测试并优化游戏逻辑和用户交互。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值