tcp Chat(poor version)
2022-11-04 18:37:53 # tcp

今天晚上闲来无事(实际上是上人工智能实验课做的这件事),找到了上计算机网络时写的有关tcp的代码,再来回顾一下。

这是一个很poor的版本,客户端的信息如果超过屏幕的高度,就会被隐藏

事实上,我也懒得挤时间去修改这个大Bug了,还有去添加发送图片、文件的功能了

从所周知,tcp协议广泛应用于我们身边。协议的接受就不再说了(三次握手四次挥手嘛😁我也忘得差不多了

服务端要先运行,否则客户端怎么能够连接到请求的主机呢。

  • start host

  • clients connect

  • client exit the dialog page

  • server’s info when client exit

以后找个时间修改修改bugs😄。

server.py

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
import socket
import threading

num = 0


def chat(connectionSocket, addr):
global num
# 新加进来的用户不在user元组中,就要向其他用户通告该用户进入进入连接的提示
if not addr in user:
print('new connection from %s:%s...' % addr)
# 向其他用户通告新用户的加入
for scs in serv_clie_socket:
serv_clie_socket[scs].send(data + " enter the room".encode('utf-8'))
# 将用户的IP+port对应的username加入到user中
user[addr] = data.decode('utf-8')
# 将用户的套接字加入到ser_clie_socket中
serv_clie_socket[addr] = connectionSocket
else:
print('%s:%s already in the room' % addr)

while True:
d = connectionSocket.recv(1024)
# 包含exit关键词退出
if (('exit' in d.decode('utf-8')) | ('break the link' in d.decode('utf-8'))):
name = user[addr]
user.pop(addr)
serv_clie_socket.pop(addr)

# 向其他用户通告某一用户的离开
for scs in serv_clie_socket:
serv_clie_socket[scs].send((name + " left the room").encode('utf-8'))
print('Connection from %s:%s closed.' % addr)

num = num - 1
# 结束该线程
print("The current number of people is " + str(num))
break
# 展示信息
else:
print('%s:%s= "%s"' % (addr[0], addr[1],d.decode('utf-8') ))
# 向其他用户通告接受的该条信息
for scs in serv_clie_socket:
if serv_clie_socket[scs] != connectionSocket:
serv_clie_socket[scs].send(d)

# 创建一个欢迎套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
addr = ('127.0.0.1', 12000)
s.bind(('',12000))
# 监听用户的请求连接,设为128个请求
s.listen(128)
print('server on', addr[0], ":", addr[1])
# 存放请求用户的(IP+端口号:用户名)的键值对
user = {}
# 存放不同用户的socket
serv_clie_socket = {}

while True:
try:
print("Waiting for request from client:")
connectionSocket, addr = s.accept()
print("received request from client")
except ConnectionResetError:
print("error")

# 从client接受到的用户名
data = connectionSocket.recv(1024)
print("user: ", data.decode())

# 创建线程 守护线程
r = threading.Thread(target=chat, args=(connectionSocket, addr), daemon=True)
r.start()
num = num + 1
print("The current number of people is ", num)

client.py

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
# 使用者端
import tkinter
from tkinter import font
import tkinter.messagebox
import socket
import threading
import time

string = ''


def Send(sock):

if string != '':
message = name + ' : ' + string
sock.send(message.encode('utf-8'))

if 'exit' in string.lower():
exit(0)


def recv(sock):
sock.send(name.encode('utf-8'))
while True:
data = sock.recv(1024)
# 获取其他用户信息的时间
time_tuple = time.localtime(time.time())
str = ("{}-{}-{} {}:{}:{}".format(time_tuple[0],time_tuple[1],time_tuple[2],time_tuple[3], time_tuple[4],time_tuple[5]))
time_recv = tkinter.Label(t,text=str,width=40,anchor='w')
time_recv.pack()
if "enter the room" in data.decode('utf-8'):
rrecv = tkinter.Label(t, text=data.decode('utf-8'), width=40, anchor='w',bg='powderblue')
elif "left the room" in data.decode('utf-8'):
rrecv = tkinter.Label(t, text=data.decode('utf-8'), width=40, anchor='w', bg='pink')
else:
rrecv = tkinter.Label(t, text=data.decode('utf-8'), width=40, anchor='w')
rrecv.pack()


# def getOnline():
# tmp = socket.recv(1024)
# data1 = tmp.d
# if "%'online is'%" in data1:
# num = []
# num = data1.dp


def left():
global string
# 得到文本框中的内容
string = rv1.get()
# 发送信息
Send(s)
if string != '':
time_tuple = time.localtime(time.time())
str = ("{}-{}-{} {}:{}:{}".format(time_tuple[0],time_tuple[1],time_tuple[2],time_tuple[3], time_tuple[4],time_tuple[5]))
# 发送时间
time_send = tkinter.Label(t,text=str,width=40,anchor='e')
time_send.pack()
# 发送信息
rleft = tkinter.Label(t, text=string, width=40, anchor='e')
rleft.pack()
rv1.set('')


def Creat():
global name
name = n.get()
# 开启一个接收信息线程
tr = threading.Thread(target=recv, args=(s,), daemon=True)
tr.start()
# 销毁之前的窗口
l.destroy()
e.destroy()
b.destroy()
# 创建主对话窗口
t.title("chatroom")
t.geometry("400x500")
rL0 = tkinter.Label(t, text='%s' % name, width=40)
rL0.pack()
rE1 = tkinter.Entry(t, textvariable=rv1,width=40)
rE1.place(x=1, y=450) # 200 450
rB1 = tkinter.Button(t, text="send", width=7, height=1, command=left)
rB1.place(x=320, y=450)



def close_chat():
# 点击窗口退出时,增加提示页面
tkinter.messagebox.showwarning(title='exit', message='exit?')
# 向服务器发送退出信息
s.send("break the link".encode('utf-8'))
exit(0)


# 创建一个客户端socket,让操作系统分配port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server = ('127.0.0.1', 12000)
s.connect(server) # 建立连接


t = tkinter.Tk()
t.title("chat")
t.geometry("300x270+500+200")

l = tkinter.Label(t, text='please input your nickname', width=40, height=10,font=('黑体',15,''))
l.pack()
n = tkinter.StringVar()
e = tkinter.Entry(t, width=20, textvariable=n,font=('黑体',15,''))
e.pack()
rv1 = tkinter.StringVar()
# 获取用户名
name = n.get()
b = tkinter.Button(t, text="login", width=30, height=40, command=Creat)
b.pack()
# 添加协议处理程序机制,点击退出按钮时,弹窗提示
t.protocol("WM_DELETE_WINDOW", close_chat)

t.mainloop()

s.close()