服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import socket
import threading
# 定义保存所有socket的列表
socket_list = []
# 创建socket对象
ss = socket.socket()
# 将socket绑定到本机IP和端口
ss.bind(('127.0.0.1', 6666))
# 服务端开始监听来自客户端的连接
ss.listen()
def read_from_client(s):
try:
return s.recv(2048).decode('utf-8')
# 如果捕获到异常,则表明该socket对应的客户端已经关闭
except:
# 删除该socket
socket_list.remove(s) # ①
def server_target(s):
try:
# 采用循环不断地从socket中读取客户端发送过来的数据
while True:
content = read_from_client(s)
print(content)
if content is None:
break
for client_s in socket_list:
client_s.send(content.encode('utf-8'))
except e:
print(e.strerror)


if __name__ == '__main__':
while True:
# 此行代码会阻塞,将一直等待别人的连接
s, addr = ss.accept()
socket_list.append(s)
# 每当客户端连接后启动一个线程为该客户端服务
threading.Thread(target=server_target, args=(s, )).start()

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Created by 秋叶夏风

# 本模块的功能:<图形化聊天界面主模块>



# 导入python系统类库
import sys

# 导入时间模块,用于获取聊天提示信息
import time

# 导入生成界面类的模块
from PyQt5 import QtCore, QtGui, QtWidgets
# 导入pyqt5类用到的类库,QApplication应用程序类,Qwidget控件的基类
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog

# 导入socket模块
import socket
import threading


# 定义连接类
class Connect:
def socket_init(self,ip):

# 创建socket对象
self.s = socket.socket()
# 连接远程主机
self.s.connect((ip, 6666))
def read_from_server(s):
global message_content
while True:
mes = s.recv(2048).decode('utf-8')
message_content += mes
print("message_content--->",message_content)
# main.form.set_label_content()
# TODO 这里在局部调用了全局的变量
# TODO 有待优化
form.set_label_content()

# 客户端启动线程不断地读取来自服务器的数据
threading.Thread(target=read_from_server, args=(self.s, )).start()


def input_chat_content(self,line):
# line = input('')
if line is None or line == 'exit':
return
# 将用户的键盘输入内容写入socket
self.s.send(line.encode('utf-8'))



# 定义UI类
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'Client_fg.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!

class Ui_Form(object):
def __init__(self):
# TODO 初始化连接,这里需要改掉,加上用户名验证
self.connect_init()


def showDialog(self):
self.name, ok = QInputDialog.getText(QWidget(), '用户登陆',
'Enter your name:')
if ok:
print(self.name)
# self.le.setText(str(text))

print(self.name+"哈哈")

# 初始化界面
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(528, 291)
self.label = QtWidgets.QLabel(Form)
self.label.setGeometry(QtCore.QRect(90, 40, 291, 121))
self.label.setObjectName("label")
self.horizontalLayoutWidget = QtWidgets.QWidget(Form)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(30, 200, 481, 80))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.lineEdit = QtWidgets.QLineEdit(self.horizontalLayoutWidget)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
self.pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)
self.pushButton.setObjectName("pushButton")
# 绑定按钮点击事件
self.pushButton.clicked.connect(self.send_message)
self.horizontalLayout.addWidget(self.pushButton)

self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)

def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", ""))
self.pushButton.setText(_translate("Form", "发送"))



def connect_init(self):
# 创建连接对象
self.c = Connect()
self.c.socket_init('127.0.0.1')
# 测试发送数据
self.c.input_chat_content("我来冒个泡!")



# TODO 这个类中的方法用到了那个模块的
def send_message(self):
name = "victor"
# 获取输入框中的内容
con = self.lineEdit.text()
# 获取现在时间
t = str(time.strftime("%H:%M:%S", time.localtime()))
new_con = "\n" + t + " " + name + "说:" + con

# 发送出去
self.c.input_chat_content(new_con)
# self.label.setText(new_con)
"""
# 设置本label显示
con = self.lineEdit.text()
# 获取现在时间
t = str(time.strftime("%H:%M:%S", time.localtime()))
new_con = self.label.text()+"\n"+t+" "+name+"说:"+con
self.label.setText(new_con)
# print()
"""
# 清空input框
self.lineEdit.setText("")

print("--------------")
print(message_content)
print("--------------")

def set_label_content(self):
self.label.setText(message_content)


if __name__ == '__main__':

# TODO 这里的显示内容的当前模块的
# TODO 在一个模块中的变量所有的类都能用上,要不然就会出现调用的时候还没定义
# TODO 而且还没有传递引用,传递的是值这就难受了

message_content = "init_content"


# 实例化App对象
app = QApplication(sys.argv)

# 实例化界面基类
w1 = QWidget()

# 实例化生成的界面的类
form = Ui_Form()
# 先输入服务端ip
# 将生成的窗体控件及配置载入到w控件对象汇总
form.setupUi(w1)
form.showDialog()
# 使用窗体显示
# 这里就执行了一次
form.set_label_content()

# 显示窗体
w1.show()

# 主消息循环
sys.exit(app.exec_())