测试代码
我们在本机模拟一次socket中的连接,即将服务端与客户端都放在本地,并且在服务端模拟了对于客户端发送数据的处理并返回。
代码中的每个函数的具体用法已放在注释中。
服务端:
# -*- coding: utf-8 -*-
import socket
import threading
def handle_tcp(sock, addr):
print("Establishing a connection from %s:%s" % addr)
# 发送TCP数据,将string中的数据发送到连接的套接字。
sock.send(b'Start!')
while True:
# 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
# bufsize的单位为bytes
data = sock.recv(1024)
if not data:
break
sock.send(b'Hello, %s!' % data)
# 关闭套接字
sock.close()
if __name__ == '__main__':
# 我们用 socket()函数来创建套接字,语法为socket.socket([family[, type[, proto]]])
# family: 套接字家族可以使AF_UNIX或者AF_INET
# type:套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
# protocol: 一般不填默认为0.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。
s.bind(('127.0.0.1', 80))
# 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
s.listen(5)
while True:
# 被动接受TCP客户端连接,(阻塞式)等待连接的到来
sock, addr = s.accept()
print ("got a connection request")
# 开启一个新的线程来处理这个socket请求
t = threading.Thread(target=handle_tcp, args=(sock, addr))
t.start()
客户端:
# -*- coding: utf-8 -*-
import socket
import time
if __name__ == '__main__':
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
s.connect(('127.0.0.1', 80))
print(s.recv(1024))
for data in [b'one', b'two', b'three']:
s.send(data)
time.sleep(1)
print(s.recv(1024))
time.sleep(1200)
s.close()
测试结果
服务端输出:
got a connection request
Establishing a connection from 127.0.0.1:61705
说明服务被正确地调起,并且客户机的端口为61705
客户端输出:
Start!
Hello, one!
Hello, two!
Hello, three!
说明客户端正确地连接到服务端,成功发送数据,并且服务端将数据进行处理并返回(“hello, one”这些为服务端返回)。
查看端口占用
先运行服务端的程序,然后打开cmd,键入:
Netstat -ano|findstr "127.0.0.1:80"
输出:
几列数据分别为:
协议 | 本地地址 | 外部地址 | 状态 | PID
我们再去看一下现在运行的python程序是不是能够对应到这个PID:
tasklist | findstr python
没有问题,PID6984确实是我们刚刚运行的python的程序的进程。
然后,再运行客户端的代码,然后在cmd中重新查看一次端口与PID:
可以看到,这里的这两个端口即为我们的服务端的进程与客户端的python的程序,且前者的源/目的地址,即为后者的目的/源地址。