手把手教你实现python网络聊天程序(可一人连续发送多句话)

  • 1. socket的使用
  • 1.1 socket的创建:
  • 1.2 socket类的常用方法
  • 1.3 socket入门实战
  • 1.3.1 TCP聊天程序(一人一句)的实现思想
  • 1.3.2 TCP聊天程序(一人一句)的实现代码
  • 2.改进我们的程序
  • 2.1改进后的思想
  • 2.2 threading模块的使用
  • 2.2.1 多线程的创建
  • 2.2.2thread的参数介绍
  • 2.2.3 threading的使用
  • 2.3tkinter模块的使用
  • 2.4最终代码


1. socket的使用

1.1 socket的创建:

s=socket.socket(AddressFamily,Type)

AddressFamily的可选参数:

可选参数

介绍

AF_INET

用于Internet进程间通讯

AF_UNIX

用于进程间通讯

Type的可选参数:

可选参数

介绍

SOCK_STREAM

流式套接字,主要用于TCP协议

SOCK_DGRAM

数据报套接字,主要用于UDP协议

1.2 socket类的常用方法

常用方法

介绍

s.bind((host,port))

绑定地址(host,port)到套接字

s.listen()

开始TCP监听,可选参数为操作系统可挂起的最大连接数量,至少为1

s.accept()

被动接收TCP客户端的连接,用阻塞的方式等待连接到来

s.connect(address)

主动初始化TCP服务链接,address格式的元组(hostname,port)若连接出错,则返回socket.error

s.recv(bufsize)

接收TCP数据,以字符串形式返回。bufsize指定接收的最大数量

s.send()

发送TCP数据,将string中数据发送到连接的套接字,返回值小于等于发送字节数

s.sendall()

完整发送TCP数据,成功返回none,失败抛出异常

s.recvfrom()

接收UDP数据,返回值为(data,address),data为包含数据的字符串,address为发送数据的地址

s.sendto()

发送UDP数据,将数据发送到套接字。(ipaddr,port)元组,指定远程地址。返回发送字节数

s.close()

关闭套接字

1.3 socket入门实战

1.3.1 TCP聊天程序(一人一句)的实现思想

python 聊天界面 python聊天代码_python

1.3.2 TCP聊天程序(一人一句)的实现代码

服务器代码:

import socket
host=’127.0.0.1’
port=996
print('服务器IP:'+host+'\n')
print('服务器端口号:'+str(port)+'\n')
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建套接字
s.bind((host,port))#绑定ip和port
s.listen(10)#设置最大监听量
sock,addr=s.accept()
print('连接已经建立')
info=sock.recv(1024).decode()
while True:
    if info:
        print('接收到的内容:'+info)
    send_data=input('输入发送内容:')
sock.send(send_data.encode())
info=sock.recv(1024).decode()
sock.close()
s.close()

客户端代码:

import socket
s=socket.socket()
host=’127.0.0.1’
port=996
s.connect((host,port))#连接服务器
print('已连接')
info=''
while True:
    send_data=input('输入发送内容:')
    s.send(send_data.encode())
    info=s.recv(1024).decode()
    print('接收的内容:'+info)
s.close()

实现效果:

python 聊天界面 python聊天代码_网络通信_02

2.改进我们的程序

现在,我们已经有了一人一句的聊天程序的铺垫,我们可以进一步实现一人可以多句的聊天程序。我们在实现的时候需要使用以下一些模块:tkinter和threading。主要思想为:每台电脑同时作为服务器和客户端,服务器只负责循环接收消息 ,而客户端只负责发送消息。

2.1改进后的思想

python 聊天界面 python聊天代码_python_03

2.2 threading模块的使用

2.2.1 多线程的创建

thread ([group[,target[,name[,args[,kwarges]]]]])

2.2.2thread的参数介绍

参数

介绍

group

值为none

target

表示一个可调用对象

name

当前线程名称

args

传递给target函数的一个参数元组

kwargs

传递给target函数的一个参数字典

2.2.3 threading的使用

我们在这个程序中只需要创建threading.thread的子类即可,示例:

import threading
class SubThread(threading.Thread):
    def run(self):
        pass#重写run方法
if __name__ == '__main__':
	p1 = SubThread()
	p1.start()

2.3tkinter模块的使用

我们在这个程序中需要使用一个按钮(Button),一个列表框(Listbox)和一个输入框(Entry),示例:

from tkinter import *
root = Tk()
v = StringVar()
thebutton = Button(root, text="send", command=send)
thebutton.grid(row=11, column=5)
thelist = Listbox(root)
thelist.grid(row=0, column=1, rowspan=10, columnspan=5)
thelist.insert(END, '1st tk')
theentry = Entry(root, textvariable=v)
theentry.grid(row=11, column=1, columnspan=4)
mainloop()

2.4最终代码

first.py

import socket
import threading
from tkinter import *


class SubThread(threading.Thread):
    def run(self):
        s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s1.bind(('127.0.0.1', 996))

        while True:
            s1.listen(10)
            sock, addr = s1.accept()
            info = sock.recv(1024).decode()
            global thelist
            thelist.insert(END, 'ta:' + info)


def send():
    s2 = socket.socket()
    s2.connect(('127.0.0.1', 669))
    global v
    s2.send(v.get().encode())
    global thelist
    thelist.insert(END, 'me:' + v.get())
    v.set('')


if __name__ == '__main__':
    root = Tk()
    v = StringVar()
    thebutton = Button(root, text="send", command=send)
    thebutton.grid(row=11, column=5)
    thelist = Listbox(root)
    thelist.grid(row=0, column=1, rowspan=10, columnspan=5)
    thelist.insert(END, '1st tk')
    theentry = Entry(root, textvariable=v)
    theentry.grid(row=11, column=1, columnspan=4)
    p1 = SubThread()
    p1.start()
    mainloop()

second.py

import socket
import threading
from tkinter import *


class SubThread(threading.Thread):
    def run(self):
        s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s1.bind(('127.0.0.1', 669))

        while True:
            s1.listen(10)
            sock, addr = s1.accept()
            info = sock.recv(1024).decode()
            global thelist
            thelist.insert(END, 'ta:' + info)


def send():
    s2 = socket.socket()
    s2.connect(('127.0.0.1', 996))
    global v
    s2.send(v.get().encode())
    global thelist
    thelist.insert(END, 'me:' + v.get())
    v.set('')


if __name__ == '__main__':
    root = Tk()
    v = StringVar()
    thebutton = Button(root, text="send", command=send)
    thebutton.grid(row=11, column=5)
    thelist = Listbox(root)
    thelist.grid(row=0, column=1, rowspan=10, columnspan=5)
    thelist.insert(END, '2nd tk')
    theentry = Entry(root, textvariable=v)
    theentry.grid(row=11, column=1, columnspan=4)
    p1 = SubThread()
    p1.start()
    mainloop()