Python网络编程-TCP在线聊天

基于TCP完成一个在线聊天程序,主要功能是实现客户端和服务器的双向通信

创建TCP Socket

s=socket.socket(scoket.AF_INET,scoket.SOCK_STREAM)

创建UDP Socket

s=socket.socket(scoket.AF_INET,scoket.SOCK_DGRAM)

面向连接TCP的时序图

socket对象的函数

TCP Socket服务器示例

# -*- coding:utf-8 -*- 
import socket

host='127.0.0.1'
port=8888
web=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
web.bind((host,port))
web.listen(10)
print('服务器等待客户端连接......')
conn,addr=web.accept()
data=conn.recv(1024).decode()
#开启循环
while True:
    while data != 'bye':
        if data:
            print('接收到:',data)
        send_data=input('发送:')
        conn.send(send_data.encode()) 
        if send_data == 'bye':
            break
        data=conn.recv(1024).decode() 
    conn.close()
    web.close()
 

TCP Socket客户端示例

import socket

client =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host='127.0.0.1'
port=8888
client.connect((host,port))
print(socket.gethostname(),'已连接!')

info=''  
while info !='bye': 
    send_data=input('发送内容:')
    client.send(send_data.encode())
    if send_data == 'bye': 
        break 
    #接收对方发过来的数据,最大接收1024字节
    info=client.recv(1024).decode()
    print('数据内容:',info)
client.close()

实现服务器和客户端双向通信 

基于tkinter的在线聊天

服务端:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Author: 人海中的海盗
# 在线聊天服务器
import tkinter
import tkinter.font as tkFont
from socket import *
import threading, time, sys

global serverSock


class ServerUI:
    local = '0.0.0.0'
    port = 9999
    flag = False
    connection = None

    def __init__(self):
        # 初始化相关属性

        self.clientMsg = None
        self.root = tkinter.Tk()
        self.root.title('Python服务器-在线聊天')
        # 窗口  4个frame面板布局
        self.frame = [tkinter.Frame(), tkinter.Frame(), tkinter.Frame(), tkinter.Frame()]
        # 显示消息的滚动条
        self.chatTextScrollBar = tkinter.Scrollbar(self.frame[0])
        self.chatTextScrollBar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
        # 显示Text,绑定滚动条
        ft = tkFont.Font(family='Fixdsys', size=11)
        self.chatText = tkinter.Listbox(self.frame[0], width=70, height=18, font=ft)
        self.chatText['yscrollcommand'] = self.chatTextScrollBar.set
        self.chatText.pack(expand=1, fill=tkinter.BOTH)
        self.chatTextScrollBar['command'] = self.chatText.yview()
        self.frame[0].pack(expand=1, fill=tkinter.BOTH)
        # 分开消息显示和消息输入
        label = tkinter.Label(self.frame[1], height=2)
        label.pack(fill=tkinter.BOTH)
        self.frame[1].pack(expand=1, fill=tkinter.BOTH)
        # 输入消息的滚动条
        self.inputTextScrollBar = tkinter.Scrollbar(self.frame[2])
        self.inputTextScrollBar.pack(side=tkinter.RIGHT, fill=tkinter.Y)

        ft = tkFont.Font(family='Fixdsys', size=11)
        self.inputText = tkinter.Text(self.frame[2], width=70, height=8, font=ft)
        self.inputText['yscrollcommand'] = self.inputTextScrollBar.set
        self.inputText.pack(expand=1, fill=tkinter.BOTH)
        self.inputTextScrollBar['command'] = self.chatText.yview()
        self.frame[2].pack(expand=1, fill=tkinter.BOTH)
        # 发送按钮
        self.sendButton = tkinter.Button(self.frame[3], text='发送', width=10, command=self.sendMessage)
        self.sendButton.pack(expand=1, side=tkinter.BOTTOM and tkinter.RIGHT, padx=25, pady=5)
        # 关闭按钮
        self.closeButton = tkinter.Button(self.frame[3], text='关闭', width=10, command=self.close)
        self.closeButton.pack(expand=1, side=tkinter.RIGHT, padx=25, pady=5)
        self.frame[3].pack(expand=1, fill=tkinter.BOTH)


    def close(self):
        self.root.destroy()

    def receiveMessage(self):
        try:
            # 建立Socket连接
            self.serverSock = socket(AF_INET, SOCK_STREAM)
            self.serverSock.bind((self.local, self.port))
            self.serverSock.listen(15)
            self.buffer = 1024
            self.chatText.insert(tkinter.END, '服务器已连接\n')
            self.flag = False
            self.accept_thread = threading.Thread(target=self.accept_connections)
            self.accept_thread.start()

        except Exception as e:
            self.chatText.insert(tkinter.END, f'服务器发生异常:{str(e)}\n')
            return  # 异常发生时结束函数执行

    def startNewThead(self):
        thread = threading.Thread(target=self.receiveMessage(), args=(), daemon=True)
        thread.start()

    def accept_connections(self):
        self.serverSock.listen(5)
        while True:
            try:
                self.connection, self.address = self.serverSock.accept()
                self.flag = True
                client_thread = threading.Thread(target=self.handle_client, args=(self.connection, self.address))
                client_thread.start()
            except Exception as e:
                print(f"Exception in accept_connections: {e}")
                break

    def handle_client(self, connection, address):
        while True:
            try:
                clientMsg = connection.recv(self.buffer).decode()
                print(clientMsg)
                if not clientMsg:
                    continue
                elif clientMsg == 'Y':
                    connection.send(b'Y')
                    self.update_chat("客户端连接成功")
                elif clientMsg == 'N':
                    connection.send(b'N')
                    self.update_chat("客户端已断开连接")
                else:
                    self.update_chat(f"客户端说: {clientMsg}")
            except Exception as e:
                self.update_chat(f"Exception: {e}")
                break

    def sendMessage(self):
        message = self.inputText.get('1.0', tkinter.END)
        theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        self.chatText.insert(tkinter.END, '服务器 ' + theTime + ' 说:'+ message + '\n')
        if self.flag:
            self.connection.send(message.encode())  # 发送到客户端
        else:
            self.chatText.insert(tkinter.END, '未与客户端建立连接\n')
        self.inputText.delete(0.0, message.__len__() - 1.0)

    def update_chat(self, message):
        self.chatText.insert(tkinter.END, message + "\n")
        self.chatText.see(tkinter.END)


def main():
    server = ServerUI()
    server.startNewThead()
    server.root.mainloop()


if __name__ == '__main__':
    main()

客户端:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Author: 人海中的海盗
# 在线聊天客户端
import tkinter
import tkinter.font as tkFont
from socket import *
import threading, time, sys

global clientSock


class ClientUI:
    local = '127.0.0.1'
    port = 9999
    flag = False

    # 初始化类的相关属性的构造函数
    def __init__(self):
        self.buffer = None
        self.clientSock = None
        self.serverMsg = None
        self.root = tkinter.Tk()
        self.root.title('Python客户端-在线聊天')
        # 窗口  4个frame面板布局
        self.frame = [tkinter.Frame(), tkinter.Frame(), tkinter.Frame(), tkinter.Frame()]
        # 滚动条
        self.chatTextScrollBar = tkinter.Scrollbar(self.frame[0])
        self.chatTextScrollBar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
        # 显示Text,绑定滚动条
        ft = tkFont.Font(family='Fixdsys', size=11)
        self.chatText = tkinter.Listbox(self.frame[0], width=70, height=18, font=ft)
        self.chatText['yscrollcommand'] = self.chatTextScrollBar.set
        self.chatText.pack(expand=1, fill=tkinter.BOTH)
        self.chatTextScrollBar['command'] = self.chatText.yview()
        self.frame[0].pack(expand=1, fill=tkinter.BOTH)
        # 分开消息显示和消息输入
        label = tkinter.Label(self.frame[1], height=2)
        label.pack(fill=tkinter.BOTH)
        self.frame[1].pack(expand=1, fill=tkinter.BOTH)
        # 输入消息的滚动条
        self.inputTextScrollBar = tkinter.Scrollbar(self.frame[2])
        self.inputTextScrollBar.pack(side=tkinter.RIGHT, fill=tkinter.Y)

        ft = tkFont.Font(family='Fixdsys', size=11)
        self.inputText = tkinter.Text(self.frame[2], width=70, height=8, font=ft)
        self.inputText['yscrollcommand'] = self.inputTextScrollBar.set
        self.inputText.pack(expand=1, fill=tkinter.BOTH)
        self.inputTextScrollBar['command'] = self.chatText.yview()
        self.frame[2].pack(expand=1, fill=tkinter.BOTH)
        # 发送按钮
        self.sendButton = tkinter.Button(self.frame[3], text='发送', width=10, command=self.sendMessage)
        self.sendButton.pack(expand=1, side=tkinter.BOTTOM and tkinter.RIGHT, padx=25, pady=5)
        # 关闭按钮
        self.closeButton = tkinter.Button(self.frame[3], text='关闭', width=10, command=self.close)
        self.closeButton.pack(expand=1, side=tkinter.RIGHT, padx=25, pady=5)
        self.frame[3].pack(expand=1, fill=tkinter.BOTH)

        self.buffer = 1024
        self.flag = False
        self.receive_thread = threading.Thread(target=self.receive_message)
        self.receive_thread.start()

    # 接收消息
    def receive_message(self):
        try:
            self.clientSock = socket(AF_INET, SOCK_STREAM)
            self.clientSock.connect((self.local, self.port))
            self.flag = True
            self.clientSock.send('Y'.encode())  # 向服务器发送字符
        except Exception as e:
            self.flag = False
            self.chatText.insert(tkinter.END, '未能与服务器建立连接\n')
            return

        while True:
            try:
                if self.flag:
                    self.server_msg = self.clientSock.recv(self.buffer).decode()
                    print(self.server_msg)
                    if not self.server_msg:
                        continue
                    elif self.server_msg == 'Y':
                        self.chatText.insert(tkinter.END, '服务器已经和客户端建立连接成功\n')
                    elif self.server_msg == 'N':
                        self.chatText.insert(tkinter.END, '服务器已经和客户端建立连接失败\n')
                    else:
                        the_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                        self.chatText.insert(tkinter.END, f'服务端 {the_time} 说:{self.server_msg}\n')
                        self.chatText.see(tkinter.END)
                else:
                    break
            except Exception as e:
                self.clientSock.send('N'.encode())
                # self.chatText.insert(tkinter.END, f'Exception: {e}\n')
                break

    def close(self):
        self.root.destroy()

    def close_connection(self):
        self.flag = False
        try:
            self.clientSock.shutdown(socket.SHUT_RDWR)
            self.clientSock.close()
        except:
            pass

    # 发送消息
    def sendMessage(self):
        message = self.inputText.get('1.0', tkinter.END)
        theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        self.chatText.insert(tkinter.END, '客户端' + theTime + '说:\n' + message + '\n')
        if self.flag:
            self.clientSock.send(message.encode())  # 发送到服务器
        else:
            self.chatText.insert(tkinter.END, '未与客户端建立连接\n')
        self.inputText.delete(0.0, message.__len__() - 1.0)

    def startNewThead(self):
        thread = threading.Thread(target=self.receive_message())
        thread.start()


def main():
    client = ClientUI()
    client.root.protocol("WM_DELETE_WINDOW", client.close_connection())
    client.root.mainloop()
    client.startNewThead()


if __name__ == '__main__':
    main()

  

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人海中的海盗

你的打赏将是对我的激励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值