多线程
需要添加模块 import threading
1 | import threading |
1 | import threading |
1 | import threading |
在 Python 中函数的递归有一定的次数限制,大概是1000,Python 执行在 pvm 中,效率不高,故不建议使用递归
通信
不能连续发送消息
服务端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#导入套接字模块socket
import socket
def main():
#创建一个用于网络连接的套接字,使用TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#绑定套接字到执行的ip和端口
server.bind(("127.0.0.1", 0x1515))
#设置套接字为监听状态,同一时刻能接收的数量
server.listen(socket.SOMAXCONN)
#等待客户端的连接
client, address = server.accept()
#和客户端使用send recv进行交互
while True:
s = input(">> ")
#发送的数据必须是bytes类型的,需要编码
client.send(s.encode())
#等待客户端的回复,接收的数据是字节,需要解码
print(client.recv(100).decode())
if __name__ == "__main__":
main()客户端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#导入套接字
import socket
def main():
#创建一个用于网络连接的套接字,使用 TCP 协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#等待客户端的连接
client.connect(("127.0.0.1", 0x1515))
#和服务端使用 send recv 进行交互
while True:
#等待服务器的回复,接收的数据是字节,需要解码
print(client.recv(100).decode())
s = input(">> ")
#发送的数据必须是 bytes 类型的,需要编码
client.send(s.encode())
if __name__ == "__main__":
main()通过线程接收消息,不需要等待
服务端:
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#导入套接字模块socket
import socket
import threading
#接收数据的线程
def reciver_thread(client):
while True:
#不断打印接收到的数据
print(client.recv(100).decode())
def main():
#创建一个用于网络连接的套接字,使用TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#绑定套接字到执行的ip和端口
server.bind(("127.0.0.1", 0x1515))
#设置套接字为监听状态,同一时刻能接收的数量
server.listen(socket.SOMAXCONN)
#等待客户端的连接
client, address = server.accept()
threading.Thread(target = reciver_thread, args = (client,)).start()
#和客户端使用send recv进行交互
while True:
s = input(">> ")
#发送的数据必须是bytes类型的,需要编码
client.send(s.encode())
if __name__ == "__main__":
main()客户端:
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#设置当前文件的编码方式,编码方式和解码方式要保持一致
#encoding: UTF-8
#导入套接字
import socket
import threading
#接收数据的线程
def reciver_thread(client):
while True:
#不断打印接收到的数据
print(client.recv(100).decode())
def main():
#创建一个用于网络连接的套接字,使用 TCP 协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#等待客户端的连接
client.connect(("127.0.0.1", 0x1515))
threading.Thread(target = reciver_thread, args = (client,)).start()
#和服务端使用 send recv 进行交互
while True:
s = input(">> ")
#发送的数据必须是 bytes 类型的,需要编码
client.send(s.encode())
if __name__ == "__main__":
main()服务端发挥其作用,作为中转站转发消息
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#导入套接字模块socket
import socket
import threading
#维护一个列表,保存所有在线的客户端
clients = []
#接收数据的线程函数
def reciver_thread(client):
while True:
try:
#这里接收到某一客户端的消息,需要转发
msg = client.recv(100)
#遍历客户端,若非自己,就转发
for i in clients:
if i != client:
i.send(msg)
except Exception as e:
#直接在列表中删除当前的客户端
for i in clients:
if i == client:
clients.remove(i)
print(client.getpeername(), "下线了")
break
#不断打印接收到的数据
print(client.recv(100).decode())
def main():
#创建一个用于网络连接的套接字,使用TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#绑定套接字到执行的ip和端口
server.bind(("127.0.0.1", 0x1515))
#设置套接字为监听状态,同一时刻能接收的数量
server.listen(socket.SOMAXCONN)
#循环等待客户端的连接
while True:
#连接到客户端,输出其地址
client, address = server.accept()
#将连接到的客户端加到在线列表中
clients.append(client)
print(address, "上线了")
#每个客户端都应有一个独立的接收数据的线程
threading.Thread(target = reciver_thread, args = (client,)).start()
if __name__ == "__main__":
main()编码
服务端:
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#encoding: utf8
# 导入套接字模块 socket
import socket
# main 函数,为主模块时执行
def main():
# 1. 创建一个用于网络连接的套接字,使用 TCP 协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定套接字到执行的 ip 和 端口,必须是元组
server.bind(("127.0.0.1", 6666))
# 3. 设置套接字为监听状态,同一时刻能接收的数量
server.listen(socket.SOMAXCONN)
# 4. 等待客户端的连接
client, address = server.accept()
# Python 向 C++ 发送一个 char*(GBK) 类型的字符串
client.send("你好".encode("gbk"))
print(client.recv(100).decode("gbk"))
# Python 向 C++ 发送一个 wchar_t*(UTF16LE) 类型的字符串
client.send("你好".encode("utf-16LE"))
print(client.recv(100).decode("utf-16LE"))
if __name__ == "__main__":
main()C++ 客户端:
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// .h文件
//包含windows网络编程必须的头文件
//传入一个表达式,并判断结果
void CheckResult(BOOL result, const char* str)
{
//如果表达式的结果为假,就报错并且结束程序
if (!result)
{
printf("%s\n", str);
system("pause"); exit(0);
}
}
//连接到服务器
SOCKET connect_server()
{
// 1. 初始化网络套接字模块
WSAData WsaData = { 0 };
if (!WSAStartup(0x0202, &WsaData))
CheckResult(0x0202 == WsaData.wVersion, "指定版本请求失败");
// 2. 创建一个套接字[IP:PORT]
SOCKET ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
CheckResult(ClientSocket != INVALID_SOCKET, "套接字创建失败");
// 4. 指定服务器的IP和地址
sockaddr_in ServerAddr = { 0 };
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(6666);
inet_pton(AF_INET, "127.0.0.1", &ServerAddr.sin_addr.S_un);
// 5. 连接到目标服务器
DWORD result = connect(ClientSocket, (sockaddr*)& ServerAddr, sizeof(ServerAddr));
CheckResult(result != SOCKET_ERROR, "连接服务器失败");
// 6. 返回套接字进行数据的收发
return ClientSocket;
}
// .cpp文件
using namespace std;
int main()
{
// 连接到服务器
SOCKET client_socket = connect_server();
// C++ 中 char 的默认编码是 GBK
char buffer[0x100] = { 0 };
recv(client_socket, buffer, 0x100, 0);
puts(buffer);
send(client_socket, "你好", 4, 0);
// C++ 中 wchar_t 的默认编码是 UTF-16LE
wchar_t buf[0x100] = { 0 };
recv(client_socket, (char*)buf, 0x100, 0);
// 将宽字符转换成多字节
printf("%s\n", CW2A(buf).m_szBuffer);
cin >> buffer;
CA2W wbuffer(buffer);
send(client_socket, (char*)wbuffer.m_szBuffer,
wcslen(wbuffer.m_szBuffer) * 2, 0);
system("pause");
return 0;
}