目录

基于tcp的简单套接字通信

简单套接字通信

服务端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import socket
#买手机
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp协议

#绑定手机
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1', 9000)) #0-65535

#开机
phone.listen(5)

#等待电话连接
print('staring....')
conn, client_addr=phone.accept() #(conn,client_addr)  .accept()会阻塞,等待建立连接。
print(conn, client_addr)

#收、发消息
data = conn.recv(1024) #1024bytes? .recv()也会阻塞。等着接收数据。
conn.send(data.upper()) #.send()不会阻塞,只是发给缓存就结束了。
#挂电话连接
conn.close()

#关机
phone.close()

客户端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import socket

#买手机
phone=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#拨电话
phone.connect(('127.0.0.1', 9000))

#发收消息
phone.send("hello".encode('utf-8'))

data = phone.recv(1024)
print(data)

#挂电话
phone.close()

结果:

1
2
3
4
5
#服务端
staring....
<socket.socket fd=360, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 18455)> ('127.0.0.1', 18455)
#客户端
b'HELLO'

优化:加上通信循环

服务端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp协议
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1', 9000)) #0-65535
phone.listen(5)
print('staring....')
conn, client_addr=phone.accept() #(conn,client_addr)
print(conn, client_addr)
while True:
    data = conn.recv(1024) #1024bytes?
    print('客户端信息', data)
    conn.send(data.upper())

conn.close()
phone.close()

客户端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import socket

phone=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 9000))
while True: #通信循环
    msg=input('>>: ').strip()
    if not msg: continue  #防止发送空信息
    phone.send(msg.encode('utf-8'))
    data = phone.recv(1024)
    print(data)

phone.close()

防止服务端死掉,添加链接循环。并捕捉异常信号,防止客户端突然断掉导致服务端死掉。相当于服务端释放无效链接。

服务端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #tcp协议
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1', 9000)) #0-65535
phone.listen(5)
print('staring....')
while True: #链接循环
    conn, client_addr=phone.accept() #(conn,client_addr)
    print(client_addr)
    while True: #通信循环
        try:
            data = conn.recv(1024) #1024bytes?
            if not data:break #针对的是Linux系统,因为linux不会抛异常。windows会抛异常。
            print('客户端信息', data)
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()
phone.close()

客户端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import socket

phone=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 9000))
while True: #通信循环
    msg=input('>>: ').strip()
    if not msg: continue  #防止发送空信息
    phone.send(msg.encode('utf-8'))
    data = phone.recv(1024)
    print(data)

phone.close()

效果,客户端突然死掉后,服务端会释放链接。当再次有新客户端来连接时,服务端会再开新链接,释放旧链接。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#服务端
staring....
('127.0.0.1', 18939)
('127.0.0.1', 18940)
('127.0.0.1', 18941)
('127.0.0.1', 18944)
#客户端
>>: 
Process finished with exit code -1
#windows会查到链接
 TCP    127.0.0.1:9000         127.0.0.1:18944        ESTABLISHED
 TCP    127.0.0.1:18944        127.0.0.1:9000         ESTABLISHED
警告
本文最后更新于 April 11, 2022,文中内容可能已过时,请谨慎使用。