Linux学习笔记(3)- 网络编程以及范例程序
前言
TCP/IP网络编程基础知识可参见1.https://blog.csdn.net/weixin_42048417/article/details/80459671?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242
网络介绍
网络的概念
实现资源共享和信息传递的虚拟平台
目的
编写基于网络通信的软件或程序
socket编程,web编程
IP地址的介绍
def: 分配给网络设备上网使用的数字标签,它能够标识网络中唯一的一台设备,好比现实生活中每个人都有一个手机号。
表现形式 为 IPv4 IPv6
作用,通过IP地址找到网络中唯一一台设备。
- ifconfig 查看网卡信息
- ping 检查网络是否正常
可在终端输入检测和了解
端口和端口号的介绍
只有ip地址是无法将信息进行传输的
每运行一个软件都有一个对应的端口,端口都对应一个端口号
端口号有65536个
通信流程
通过IP地址找到对应的设备,通过端口号找到对应的端口,然后通过端口把数据给应用程序。
端口是传输数据通道,是数据传输的必经之路
端口号是用来管理区分不同端口的一个号码
-
端口号的分类
-
知名端口号
众所周知的端口号,0-1023;比如 21给ftp,25给SMTP等
-
动态端口号
开发应用程序使用端口号,1024-65535
-
socket介绍
IP地址+端口号+工具(socket)
socket(简称 套接字)网络数据通讯的工具
TCP介绍
在发送数据之前要选择网络传输方式(传输协议),保证程序之间按照指定的传输规定进行数据的通信。
Transmission Control Protocol 简称传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议
char1 面向连接
- 通信步骤:(类似于打电话,在通信开始前要建立连接,才能发送数据,通信结束要关闭连接)
- 创建连接(双方为此连接分配必要的资源来记录连接的状态和信息)
- 传输数据
- 关闭连接(释放系统资源)
char2 可靠性
- TCP采用发送应答机制
- 每个报文段都必须接到对方的应答
- 超时重传
- 启动定时器
- 错误校验
- 校验和函数
- 流量控制和阻塞管理
- 避免发送端发送过快使得接收方来不及接收
python3编码转换
- 网络传输是以二进制数据进行传输的
- encode 编码 将字符串转换为字节码
- decode 解码 将字节串转换为字符码
- bytes.encode(encoding = “utf-8”)
- str.encode(encoding = “utf-8”)
TCP客户端程序开发流程
TCP客户端程序开发 运行在用户设备上的程序
TCP服务端程序开发 运行在服务器设备上的程序,专门为客户端提供数据服务
流程图
- 客户端开发流程
- 创建客户端套接字对象(买电话)
- 和服务端套接字建立连接(打电话)
- 发送数据
- 接收数据
- 关闭客户端套接字(挂电话)
知识要点
- TCP网络应用程序开发分为 客户端程序开发和服务端程序开发
- 主动发起建立连接请求的是客户端程序
- 等待接受连接请求的是服务端程序
范例 :
-
socket类的介绍
-
导入socket模块
import socket
-
创建客户端socket对象
socket.socket(AddressFamily, Type)
参数名 说明 AddressFamily IP地址类型,分为IPv4和IPv6 (AF_INET 表示IPV4,
SOCK_STREAM表示TCP传输协议类型)Type 传输协议类型
-
-
开发客户端使用到的函数
方法名 说明 connect 和服务端套接字建立连接 send 发送数据 需注意encode编码 recv 接收数据 需注意decode解码 close 关闭连接 -
import socket if __name__ == "__main__": # 1. 创建客户端套接字对象(买电话) tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2. 和服务端套接字建立连接(打电话) tcp_client_socket.connect(("192.168.99.1",8080)) # 3. 发送数据 tcp_client_socket.send("nihaoma".encode(encoding = "utf-8")) # 4. 接收数据,阻塞等待数据的到来 recv_data = tcp_client_socket.recv(1024) print(recv_data.decode()) # 5. 关闭客户端套接字(挂电话) tcp_client_socket.close()
#执行结果 [2021-03-14 22:37:42.270] nihaoma [2021-03-14 22:37:46.730]# SEND ASCII TO ALL> http://www.cmsoft.cn
本案例中使用网络调试助手作为TCP服务端,可查看电脑对应的IP地址。网络调试助手下载链接为https://download.csdn.net/download/weixin_43357695/15791548
-
客户端开发流程
- 创建服务端套接字对象
- 绑定IP地址和端口号
- 设置监听
- 等待接收客户端的连接请求
- 接收数据
- 发送数据
- 关闭客户端套接字
-
范例
-
socket类的介绍(同客户端)
-
开发服务端使用到的函数
方法名 说明 blind 绑定IP地址和端口号 元组中第一个元素是ip地址,一般不需要设置,
第二个是启动程序后使用的端口号listens 设置监听,参数为最大等待连接数 accept 等待接受客户端的连接请求 send 发送数据 需注意encode编码,要发送的二进制数据 recv 接收数据 解码成字符串需注意decode解码,参数为每次接受数据的大小,
单位是字节 -
import socket if __name__ == "__main__": # 1. 创建服务端套接字对象 tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置端口复用(linux下可能存在再次运行端口被占用的情况) tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 2. 绑定IP地址和端口号 # tcp_server_socket.bind(("192.168.125.115",8888)) #若blind的参数第一个ip地址元素为“”,则默认本机IP地址 tcp_server_socket.bind(("",8888)) # 3. 设置监听 128:代表服务器中等待排队连接的最大数量 tcp_server_socket.listen(128) # 4. 等待接收客户端的连接请求 accept()阻塞等待,返回一个用以和客户端通信的socket,客户端的地址 comu_socket, ip_port = tcp_server_socket.accept() print("客户端地址:", ip_port) # 5. 接收数据 recv_data = comu_socket.recv(1024) # print("接收到的数据:", recv_data.decode()) print("接收到的数据:", recv_data.decode('gbk'))#中文解码 # 6. 发送数据 comu_socket.send("客户端你的数据我接收到啦".encode("gbk")) # 7. 关闭客户端套接字 comu_socket.close() tcp_server_socket.close()
#执行结果 #网络调试助手 [2021-03-14 23:37:17.562]# SEND ASCII> 你好啊 [2021-03-14 23:37:17.600]# RECV ASCII> 客户端你的数据我接收到啦 #编译器 >>> %Run '网络编程_服务端开发.py' 客户端地址: ('192.168.125.115', 3606) 接收到的数据: 你好啊
-
-
TCP网络应用程序注意点
- 当TCP客户端程序想要和TCP服务端斤西瓜通信的时候必须先建立连接
- TCP客户端一般不要绑定端口号,因为客户端时主动发起建立连接的
- TCP服务端必须绑定端口号,否则客户端找不到这个TCP服务端程序
- listen后的套接字是被动套接字,只负责接收新的客户端的连接请求,不能收发消息
- 当TCP客户端程序和TCP服务端程序连接成功后,TCP服务器程序会产生一个新的套接字,收发客户端消息使用该套接字
- 关闭accept返回的套接字意味着和这个客户端已经通信完毕
- 当客户端的套接字调用close后,服务端的recv会解阻塞,返回的数据长度为0,服务端可以通过返回数据的长度来判断客户是否有已经下线,反之服务端关闭套接字,客户端的recv也会解阻塞,返回数据长度也为0
-
知识要点
-
TCP socket的发送和接收缓冲区
- 当创建一个TCP socket对象的时候会有一个发送缓冲区和一个接收缓冲区,指内存中一片空间
-
send是不是直接把数据发给服务端
- 不是,要想发送数据,必须通过网卡发送数据,应用程序无法直接通过网卡发送数据,它需要调用操作系统接口,也就是说应用程序先把发送的数据写入到发送缓冲区(内存中的一片空间),再有操作系统控制网卡把发送缓冲区的数据发送给服务端网卡
-
recv是不是直接从客户端接收数据
- 不是,与send相反,接收缓冲区
发送与接收数据都是由网卡完成的。
-
多任务版TCP服务器程序开发
一个服务端服务多个客户端
步骤分析:
-
编写一个TCP服务端程序,循环等待接收客户端的连接请求
-
import socket if __name__ == "__main__": # 1. 创建服务端套接字对象 tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置端口复用(linux下可能存在再次运行端口被占用的情况) tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 2. 绑定IP地址和端口号 # tcp_server_socket.bind(("192.168.125.115",8888)) #若blind的参数第一个ip地址元素为“”,则默认本机IP地址 tcp_server_socket.bind(("",8888)) # 3. 设置监听 128:代表服务器中等待排队连接的最大数量 tcp_server_socket.listen(128) while True:#循环等待客户端的连接请求 # 4. 等待接收客户端的连接请求 accept()阻塞等待,返回一个用以和客户端通信的socket,客户端的地址 comu_socket, ip_port = tcp_server_socket.accept() print("客户端地址:", ip_port) # 5. 接收数据 recv_data = comu_socket.recv(1024) # print("接收到的数据:", recv_data.decode()) print("接收到的数据:", recv_data.decode('gbk'))#中文解码 # 6. 发送数据 comu_socket.send("客户端你的数据我接收到啦".encode("gbk")) # 7. 关闭客户端套接字 comu_socket.close() tcp_server_socket.close()
-
-
第一步不能实现同时服务多个客户端,联系多任务(进程与线程)
当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞
import socket import threading #处理客户端函数 def handle_client(comu_socket): # 5. 接收数据 recv_data = comu_socket.recv(1024) # print("接收到的数据:", recv_data.decode()) print("接收到的数据:", recv_data.decode('gbk'))#中文解码 # 6. 发送数据 comu_socket.send("客户端你的数据我接收到啦".encode("gbk")) # 7. 关闭客户端套接字 comu_socket.close() if __name__ == "__main__": # 1. 创建服务端套接字对象 tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置端口复用(linux下可能存在再次运行端口被占用的情况) tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 2. 绑定IP地址和端口号 # tcp_server_socket.bind(("192.168.125.115",8888)) #若blind的参数第一个ip地址元素为“”,则默认本机IP地址 tcp_server_socket.bind(("",8888)) # 3. 设置监听 128:代表服务器中等待排队连接的最大数量 tcp_server_socket.listen(128) while True: # 4. 等待接收客户端的连接请求 accept()阻塞等待,返回一个用以和客户端通信的socket,客户端的地址 comu_socket, ip_port = tcp_server_socket.accept() print("客户端地址:", ip_port) # 使用多线程去接受多个客户端的请求 sub_thread = threading.Thread(target = handle_client, args = (comu_socket,)) sub_thread.start() tcp_server_socket.close()
执行结果:
%Run '多任务版服务端.py'(同时打开多个网络调试助手进行连接和传输) 客户端地址: ('192.168.125.116', 16764) 接收到的数据: http://www.cmsoft.cn 客户端地址: ('192.168.125.116', 16774) 客户端地址: ('192.168.125.116', 16778) 接收到的数据: 2222 客户端地址: ('192.168.125.116', 16800) 接收到的数据: 3333 接收到的数据: 2222
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。