01-基本概念
IP地址
类似: 192.168.1.105 标记一台唯一的电脑 在本地局域网内是唯一的
ipv4(主流) ipv6(还在发展)
ipv4 前三组数是网络号,后面一组数是主机地址 192.168.1.1~254 C类地址最常用
端口:(通道)
端口号:进一步分辨是哪一个程序接收和发送数据 (门牌号)
dest ip: 目的IP src IP :源IP
dest port:目标端口 src port :源端口
进程就是运行起来的程序
知名端口:80端口分配给http服务 21端口分配给FTP服务 范围是0-1023 动态端口:1024-65535
socket
用来完成网络功能的必备工具
创建一个tcp socket(tcp套接字)
import socket #导入socket模块
# 创建tcp的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #第一个参数是协议族(默认ipv4) 第二个参数是类型
# ...这里是使用套接字的功能(省略)...
# 不用的时候,关闭套接字
s.close()
创建一个udp socket(udp套接字)
import socket
# 创建udp的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# ...这里是使用套接字的功能(省略)...
# 不用的时候,关闭套接字
s.close()
套接字使用流程 与 文件的使用流程很类似
- 创建套接字
- 使用套接字收/发数据
- 关闭套接字
先绑定端口然后在循环发送数据
import socket
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定本地信息
udp_socket.bind(("", 7890))
while True:
# 从键盘获取数据
send_data = input("请输入要发送的数据:")
# 可以使用套接字收发数据
# udp_socket.sendto("hahahah", 对方的ip以及port)
# udp_socket.sendto(b"hahahah------1----", ("192.168.33.53", 8080))
udp_socket.sendto(send_data.encode("utf-8"), ("192.168.33.53", 8080))
# 关闭套接字
udp_socket.close()
if __name__ == "__main__":
main()
循环接收并显示数据
import socket
def main():
# 1. 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2. 绑定一个本地信息
localaddr = ("", 7788)
udp_socket.bind(localaddr) # 必须绑定自己电脑的ip以及port,其他的不行
# 3. 接收数据
while True:
recv_data = udp_socket.recvfrom(1024)
# recv_data这个变量中存储的是一个元组(接收到的数据,(发送方的ip, port))
recv_msg = recv_data[0] # 存储接收的数据
send_addr = recv_data[1] # 存储发送方的地址信息
# 4. 打印接收到的数据
# print(recv_data)
# print("%s:%s" % (str(send_addr), recv_msg.decode("utf-8")))
print("%s:%s" % (str(send_addr), recv_msg.decode("gbk")))
# 5. 关闭套接字
udp_socket.close()
if __name__ == "__main__":
main()
函数与函数之间空两行
注释:在一行段首位置写注释 #号之后 空一个空格 然后写注释 在非段首位置写注释,在代码之后 空两个空格之后写#号,然后空一个空格,然后写注释
格式化输出的时候,%号与双引号之间有一个空格
TCP:传输控制协议 (稳定,更可靠) UDP:用户数据报协议(数据不安全,数据可能丢失)
TCP严格控制客户端和服务器
tcp-客户端(client)客户端代码:
import socket
def main():
# 1. 创建tcp的套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 链接服务器
# tcp_socket.connect(("192.168.33.11", 7890))
server_ip = input("请输入要链接的服务器的ip:")
server_port = int(input("请输入要链接的服务器的port:"))
server_addr = (server_ip, server_port)
tcp_socket.connect(server_addr)
# 3. 发送数据/接收数据
send_data = input("请输入要发送的数据:")
tcp_socket.send(send_data.encode("utf-8"))
# 4. 关闭套接字
tcp_socket.close()
if __name__ == "__main__":
main()
tcp-服务器(server) 【循环为多个客户端服务并且多次服务一个客户端】 代码
import socket
def main():
# 1. 买个手机(创建套接字 socket)
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 插入手机卡(绑定本地信息 bind)
tcp_server_socket.bind(("", 7890))
# 3. 将手机设置为正常的 响铃模式(让默认的套接字由主动变为被动 listen)
tcp_server_socket.listen(128)
# 循环目的:调用多次accept,从而为多个客户端服务
while True:
print("等待一个新的客户端的到来...")
# 4. 等待别人的电话到来(等待客户端的链接 accept)
new_client_socket, client_addr = tcp_server_socket.accept()
print("一个新的客户端已经到来%s" % str(client_addr))
# 循环目的: 为同一个客户端 服务多次
while True:
# 接收客户端发送过来的请求
recv_data = new_client_socket.recv(1024)
print("客户端福送过来的请求是:%s" % recv_data.decode("utf-8"))
# 如果recv解堵塞,那么有2种方式:
# 1. 客户端发送过来数据
# 2. 客户端调用close导致而了 这里 recv解堵塞
if recv_data:
# 回送一部分数据给客户端
new_client_socket.send("hahahghai-----ok-----".encode("utf-8"))
else:
break
# 关闭套接字
# 关闭accept返回的套接字 意味着 不会在为这个客户端服务
new_client_socket.close()
print("已经为这个客户端服务完毕。。。。")
# 如果将监听套接字 关闭了,那么会导致 不能再次等待新客户端的到来,即xxxx.accept就会失败
tcp_server_socket.close()
if __name__ == "__main__":
main()