Python实验:Socket编程
实验六 Socket 编程
一、实验目标:
了解TCP协议原理、标准库socket 的用法、熟悉Socket 编程。
1.TCP协议原理:
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于流的协议,用于在计算机网络中传输数据。它是互联网协议套件中的一部分,通常与IP(Internet Protocol,互联网协议)一起使用,形成TCP/IP协议栈。
- 面向连接:TCP是一种面向连接的协议,这意味着在数据传输之前需要在通信的两端建立连接。建立连接的过程包括三次握手,确保双方都能够正确通信。
- 可靠性:TCP提供可靠的数据传输。它使用序号和确认机制来确保数据的可靠传输。每个数据包都有一个唯一的序号,接收端会发送确认来告诉发送端已成功接收数据。如果发送端没有收到确认,它将重传数据,直到确认被接收。
- 流控制:TCP使用流控制机制来控制数据的发送速率,以确保接收端不会被过多的数据淹没。这是通过TCP窗口大小来实现的,接收端告诉发送端它可以接收多少数据,以避免数据丢失或过载。
- 拥塞控制:TCP也具有拥塞控制机制,用于防止网络拥塞。它使用拥塞窗口来限制数据发送速率,以适应网络的容量,避免过多的数据导致拥塞。
- 有序数据传输:TCP保证数据包的有序传输。即使数据包在传输过程中乱序到达,接收端会按照正确的顺序将它们重新排序。
- 双工通信:TCP支持全双工通信,这意味着双方可以同时发送和接收数据,而不需要等待对方的响应。
- 数据分段:TCP将数据分成适当的数据段,并在每个数据段中添加头部信息,包括序号、确认号、标志位等,以便进行数据传输和控制。
- 错误检测和纠正:TCP包含校验和机制,用于检测传输过程中的错误。如果数据包被损坏,它将被丢弃,要求重传。
2.标准库socket的用法
1.创建一个TCP服务器套接器:
import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 使用IPv4和TCP协议 server_socket.bind(("0.0.0.0", 8888)) # 绑定套接字到指定的端口 server_socket.listen(5) # 开始监听客户端连接,设置连接队列的大小为5
2.创建一个TCP客户端套接字:
import socket # 创建一个TCP客户端套接字 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 连接到服务器 client_socket.connect(("server_ip", 8888))
3.接受客户端连接和处理:
import socket # 创建一个TCP服务器端套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(("0.0.0.0", 8888) server_socket.listen(5) # 接受客户端连接 client_socket, client_address = server_socket.accept() # 处理客户端请求 data = client_socket.recv(1024) client_socket.send("Hello, Client!".encode('utf-8')) # 关闭套接字连接 client_socket.close()
4.发送和接收数据:
import socket # 创建一个TCP客户端套接字 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect(("server_ip", 8888)) # 发送数据到服务器 client_socket.send("Hello, Server!".encode('utf-8')) # 从服务器接收数据 data = client_socket.recv(1024) print(data.decode('utf-8')) # 关闭客户端套接字连接 client_socket.close()
二、实验内容:
(1) 使用TCP协议实现智能聊天机器人。编写聊天程序的服务端代码和客户端代码。完成后,先启动服务端代码,然后启动客户端程序用输入问题,服务端可以返回相应的答案。要求服务端代码具有一定的智能,能够根据不完整的问题识别客户端真正要问的问题。(问题和答案是预先定义好的)要求支持多线程。
服务端代码:
import socket import threading # 用于处理多个客户端连接的多线程支持 import re question_anwers = { '你好': "你好,有什么可以帮助你的吗?", "现在几点了":"现在20:46", "你叫什么名字": "我叫chatGBT", "你会做什么": "我会回答一些基本问题", "再见": "再见,愚蠢的人类", "天气查询": "今天最高温度达到27℃", "时间查询": "请看右下角" } def identify_intension(question): question = question.lower() if re.search("天气",question): return "天气查询" if re.search("时间",question): return "时间查询" if re.search("你会什么",question): return "你会做什么" if re.search("你叫什么",question): return "你叫什么名字" if re.search("你是",question): return "你叫什么名字" if re.search("几点了",question): return "现在几点了" for key in question_anwers: #模糊匹配 if key in question: return key def handle_client(client_socket): while True: question = client_socket.recv(1024).decode('utf-8') if not question: break intension = identify_intension(question) if intension in question_anwers: answer = question_anwers[intension] else: answer="我不知道怎么回答这个问题" client_socket.send(answer.encode('utf-8')) client_socket.close() def main(): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建服务器套接字,使用IPv4协议和TCP协议 server.bind(("0.0.0.0", 8888)) server.listen(5) print("服务器已启动,等待连接……") while True: client_socket, addr = server.accept() print("接收到的连接来自 %s:%s" % (addr[0], addr[1])) client_handler = threading.Thread(target=handle_client, args=(client_socket,)) client_handler.start() if __name__ == '__main__': main()
客户端代码:
import socket def main(): client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(("127.0.0.1",8888)) while True: question = input("请输入你的问题(或输入exit以退出)") if question.lower()=='exit': break client.send(question.encode('utf-8')) response = client.recv(1024).decode('utf-8') print(response) client.close() if __name__=="__main__": main()
(2) 使用UDP协议打造在线时间服务器。服务端监听特定的端口,如果收到客户端发来的请求就把服务器上的当前时间发给客户端,而客户端收到时间之后立刻打印输出。
服务端:
import socket import time server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_address = ("0.0.0.0", 8888) server_socket.bind(server_address) print("时间服务器已启动,等待请求...") while True: data, client_address = server_socket.recvfrom(1024) if data.decode('utf-8') == "时间": current_time = time.ctime() server_socket.sendto(current_time.encode('utf-8'), client_address)
客户端:
import socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_address = ("127.0.0.1", 8888) request = "时间" client_socket.sendto(request.encode('utf-8'), server_address) # 接收服务器的时间响应 data, server_address = client_socket.recvfrom(1024) print("服务器时间:", data.decode('utf-8'))
(3) 使用socketserver模块建立基于tcp协议通信的服务,收到客户端发来的英文字符串之后,将其变为大写发回客户端。
服务端代码:
import socketserver class MyTCPhandler(socketserver.BaseRequestHandler): # 定义一个自定义的处理器类 def handle(self): while True: # 持续接收 try: data = self.request.recv(1024) # 从客户端接受数据 print('收到客户端的消息: ', data) # 打印接收的数据 self.request.send(data.upper()) # 转换成大写发送到客户端 except ConnectionResetError: # 如果连接异常,就退出 break self.request.close() if __name__ == '__main__': server = socketserver.ThreadingTCPServer(('127.0.0.1', 8888), MyTCPhandler) print("服务端已启动") server.serve_forever()
客户端代码:
from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(('127.0.0.1', 8888)) # 通信循环 print("客户端已启动,输入exit()退出") while True: data = input("请输入要发送的数据:") if data == 'exit()': break client.send(data.encode('utf-8')) Data = client.recv(1024) print(Data) client.close()
(4) 编写代码对网络上的ip地址进行端口扫描,收集“ip+开放端口”信息。进一步的,尝试了解和使用流行的网络扫描工具进行扫描,如zmap,nmap,并写出使用过程和扫描结果。
python实现:
import socket def scan_port(ip): for port in range(1, 1000): p = socket.socket(socket.AF_INET, socket.SOCK_STREAM) p.settimeout(0.1) respond = p.connect_ex((ip, port)) if respond == 0: print(f"主机{ip},端口{port}已开放") p.close() print("扫描完毕") target_host = input("请输入ip:") scan_port(target_host)
尝试扫描 baidu.com
先ping一下baidu.com
然后进行端口扫描:
Nmap扫描:
尝试扫描 github.com
本文作者:Smera1d0
本文链接:https://www.cnblogs.com/Smera1d0/p/17818491.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步