1. IP 地址
概念: 标识网络中设备的地址(需要联网才有没有联网, 是没有这个地址)
表现形式:
ipv4
目前主要使用的, 点分十进制的格式,(192.168.3.43)
- 分为 4 段, 每段的范围是
0-255
,0.0.0.0 ~ 255.255.255.255
- 公网 IP, 可以直接被别人使用访问的 ip(需要购买)
- 局域网 ip(内网), 通过路由器或者交换机得到的 ip 都是局域网 ip, 只有处于同一个局域网的才能使用这个 ip, 电脑中查看到的 ip 都是局域网 ip.
-
ipv6
冒号 16 进程的格式
作用: IP地址可以标识网络中唯一的一台设备
查看 IP 地址
- Linux 和 Mac :
ifconfig
- Windows :
ipconfig
查看网络是否正常ping
-
ping 公网 ip
是否可以联外网,ping www.baidu.con
-
ping 局域网的 ip
检查是否在同一个局域网,设备是否连通
域名: 是 ip 地址的别名, 方便记忆, (DNS 服务器, 将域名转换为 ip 地址)
-
127.0.0.1
本机的 ip 地址, 对应的域名localhost
2. 端口
端口: 数据传输的通道
端口号: 是端口的唯一标识, 是一个整型数字(int)
端口的分类0-65535
一共 65536个
- 知名端口
0-1023
- http 协议
80
- https :
443
- ssh
22
- 动态端口
1024-65535
通过 ip 找到某台主机, 设备
通过端口号,能对应主机中的一个应用程序
IP + 端口: 标识网络中唯一的一个应用程序
3. TCP
概念: 传输控制协议(主机间通信传输数据的规则)
特点:
- 面向连接的(通信之前, 必须先建立连接)
- 数据是可靠的
- 发送应答
- 超时重传
- 错误校验
- 流量控制
通信步骤:
- 建立连接
- 传输数据(通信)
- 关闭连接
传输协议: TCP UDP
4. scoket
- socket, 套接字, 进程间网络通信的工具.
- 使用场景: 所有的网络通信的底层都会使用 socket
5. TCP 客户端
# 1. 创建 socket 对象 socket.socket()
# 2. 和服务器建立连接 socket对象.connect()
# 3. 发送数据给服务器 socket对象.send()
# 4. 客户端接收服务器发送的信息 socket对象.recv()
# 5. 关闭连接 socket对象.close()
# (3. 4 可以重复进行)
python 中的字符串
str: 使用引号引起来的就是字符串
bytes: 二进制类型的数据
str --> bytes str.encode(编码类型)
bytes--> str bytes.decode(编码类型)
程序代码:
import socket
# 1. 创建 socket 对象
# socket.AF_INET 表示 ipv4 AF_INET6 表示 ipv6
# socket.SOCK_STREAM 表示 tcp协议
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 和服务器建立连接(参数是元组)
client_socket.connect(('192.168.1.5', 8080))
print('和服务器建立连接成功')
# 3. 发送数据给服务器
# 3.1 准备数据(bytes)
send_info = '你好服务器'.encode()
# 3.2 发送数据
client_socket.send(send_info)
# 4. 客户端接收服务器发送的信息,参数表示一次接收多少字节
buf = client_socket.recv(4096)
try:
print(f'接收到: {buf.decode()}')
except UnicodeError:
print(f'接收到: {buf.decode("gbk")}')
# 5. 关闭连接
client_socket.close()
程序输出:
和服务器建立连接成功
接收到: 你好
注意点:
- 必须先启动服务器
- connect 是元组类型, 服务器的 ip 和端口不要写错
6. TCP 服务端
# 1. 创建 socket 对象
# 2. 绑定 IP 和端口
# 3. 设置监听, 将主动套接字变为被动套接字
# 4. 等待客户端链接阻塞等待
# 5. 接收客户端的信息
# 6. 给客户端发送信息
# 7. 关闭套接字
程序代码:
import socket
# 1. 创建 socket 对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定 IP 和端口(参数是元组)
server_socket.bind(('', 9999)) # IP 地址为空表示绑定的是王机中任意一个ip
# 3. 设置监听, 将主动套接字变为被动套接字,参数表示最多允许多少客户端同时请求服务器(不包括已经连接成功的)
server_socket.listen(128)
# 4. 等待客户端链接阻塞等待
print('等待客户端连接')
# 返回值是元组类型(用于通信socket,客户端的 IP 和端口
new_socket, ip_port = server_socket.accept()
print(f'客户端 {ip_port} 上线')
# 5. 接收客户端的信息
buf = new_socket.recv(4096)
print(f'接收到: {buf.decode()}')
# 6. 给客户端发送信息
new_socket.send('信息收到'.encode())
# 7. 关闭套接字
new_socket.close()
server_socket.close()
程序输出:
等待客户端连接
客户端 ('192.168.1.5', 65439) 上线
接收到: 你好服务器
设置端口复用:
# 参数1 level,设置哪个级别的socket, socket.SOL_SOCKET当前的socket(固定写法)
# 参数2 option, 设置什么内容, socket.SO_REUSEADDR 端口复用
# 参数3 将内容设置为什么值, True
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
判断客户端断开连接:
# buf: 字符串(容器)都可以直接作为 bool 类型进行判断,当容器中元素的个数为 0, 是 False, 其余是 True
if len(buf) == 0:
pass
if buf: # if not buf:
pass
7. 多任务 TCP 服务端
程序代码:
import socket
import threading
def handle_client_request(new_socket, ip_port):
while True:
buf = new_socket.recv(4096)
if buf:
try:
print(f'接收到: {buf.decode()}')
new_socket.send('信息收到'.encode())
except UnicodeDecodeError:
print(f'接收到: {buf.decode("gbk")}')
new_socket.send('信息收到'.encode("gbk"))
else:
print(f'{ip_port} 下线')
break
new_socket.close()
if __name__ == '__main__':
# 1. 创建 socket 对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口复用
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 2. 绑定
server_socket.bind(('', 9999))
# 3. 设置监听
server_socket.listen(128)
# 4. 循环等待客户端链接阻塞等待
print('等待客户端连接')
while True:
# 返回值是元组类型,(用于通信socket,客户端的Lio和端口port】,拆包
new_socket, ip_port = server_socket.accept()
print(f'客户端 {ip_port} 上线')
sub_thread = threading.Thread(target=handle_client_request, args=(new_socket, ip_port))
sub_thread.start()
注意:
- 线程要启动 start()
- new_socket.close() 位置要正确