socket
来源:互联网 发布:api打印编程 编辑:程序博客网 时间:2024/06/06 17:56
socket—–套接字基础
创建socket
import sockettcpsock = socket.socket(socket.AF_INET,socket.SOCK_STREM)#创建Tcp/Ip套接字udpsock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#创建UDp/Ip套接字
内置方法
创建一个TCP服务器(伪代码)
import socketss = socket.socket() # 创建服务器套接字 ss.bind() #套接字与地址绑定ss.listen() #监听连接 可传入最大连接数inf_loop: #服务器无限循环 cs = ss.accept() #接收客户端连接 简单的(单线程) comm_loop: #通信循环 cs.revc()/cs.send() #对话(接收/发送) cs.close() #关闭客户端套接字ss.close() #关闭服务器套接字 (可选)
TCp时间戳服务器(tsTserv.py)
这个脚本创建一个Tcp服务器,他接收来自客户端的消息,然后将消息加上时间戳前缀并发送回客户端
from socket import *from time import ctimeHOST = 'localhost'PORT = 9999BUFSIZ = 1024ADDR = (HOST, PORT)tcpSerSock = socket(AF_INET, SOCK_STREAM)tcpSerSock.bind(ADDR)tcpSerSock.listen(5)while True: print('waiting for connection..') tcpCliSock ,addr = tcpSerSock.accept() print('...connected from', addr) while True: data = tcpCliSock.recv(BUFSIZ) if not data: break tcpCliSock.send('[%s] %s' %(bytes(ctime(), 'utf-8'), data)) tcpCliSock.close()tcpSerSock.close()
创建一个TCP客户端(伪代码)
import socket cs = socket.socket() #创建客户端套接字cs.connect() #尝试连接服务器comm_loop: #通信循环 cs.send()/cs.recv() #对话(接收/发送)cs.close() #关闭客户端套接字
TCp时间戳客户端(tsTcln.py)
from socket import *HOST = 'localhost'PORT = 9999BUFSIZ = 1024ADDR = (HOST, PORT)tcpCliSock = socket(AF_INET, SOCK_STREAM)tcpCliSock.connect(ADDR)while True: data = input('<<:') if not data: print('输入为空!') continue tcpCliSock.send(data.encode('utf-8')) data = tcpCliSock.recv(BUFSIZ) if not data: print('服务器端异常') break print(data.decode())tcpCliSock.close()
socketserver模块
socketserver是标准库的一个高级模块,它的目标是简化很多样板代码,隐藏的实现细节之外,另一个不同之处就是,我们现在使用累来编写应用程序。因为以面向对象的方式处理事务有助于组织数据,以及逻辑性的将功能放在正确的地方,你还会注意到,应用程序现在是事件驱动的,这以为着只有在系统中的事件发生时,它们才会工作。
socketserver模块类
用socketserver实现tsTserv.py
from socketserver import (TCPServer as TCP, StreamRequestHandler as SRH)from time import ctimeHOST = ''PORT = 9999ADDR = (HOST, PORT)BUFSIZ = 1024class MyRequestHandler(SRH): def handle(self): print('..connected from:', self.client_address) self.request.send(('[%s] %s' %(ctime(), self.request.recv(BUFSIZ).decode())).encode('utf-8'))if __name__ == '__main__': tcpServ = TCP(ADDR, MyRequestHandler) print('waiting for connection..') tcpServ.serve_forever()
我们得到了请求处理程序MyRequestHandler,作为socketserver中StreamRequestHandler的一个子类,重写了handle()方法,该方法在基类Request中默认情况下没有任何行为
def handle(self): pass
当接收到一个来自客户端的消息时,他就会调用handle()方法。
在socket中用recv()和send()来表示接收/发送 而在socketserver中self.request.recv()和self.request.send()来表示接收/发送
最后利用给定的主机欣喜和请求处理创建了TCP服务器。然后,无限循环的等待并服务于客户端请求
用socketserver实现tsTcln.py
from socket import *HOST ='localhost'PORT = 9999BUFSIZ = 1024ADDR = (HOST, PORT)tcp = socket(AF_INET, SOCK_STREAM) tcp.connect(ADDR)while True: data = input('>>:') if not data: continue tcp.send(bytes(data, 'utf-8')) data = tcp.recv(BUFSIZ) if not data: break print(data.decode().strip()) tcp.close()
socketserver请求处理程序的默认行为是接收连接、获取请求,然后关闭连接。由于这个原因,我们不能在应用程序整个执行过程中都保持连接,因此每次向服务器发送信息时,都需要创建一个新的套接字
运行时可以发现,我们还是只能连接一个客户端,当第一个连接没有关闭时,第二个连接一直在等待,如何实现同时连接呢?
很简单,我们将服务端稍作修改;
# from socketserver import (TCPServer as TCT,# StreamRequestHandler as SRH)import socketserver #这里只导入socketser并不进行导入具体方法from time import ctimeHOST = ''PORT = 9999ADDR = (HOST, PORT)BUFSIZ = 1024class MyRequestHandler(socketserver.StreamRequestHandler):#这里和以前一样 只是换了一个写法 def handle(self): print('..connected from:', self.client_address) self.request.send(('[%s] %s' %(ctime(), self.request.recv(BUFSIZ).decode())).encode('utf-8'))if __name__ == '__main__': tcpServ = socketserver.ThreadingTCPServer(ADDR, MyRequestHandler)# tcpServ 并不是socketserver.TCPServer 而是socketserver.ThreadingTCPServer 就是字面意思 ThreadingTCPServer 使用的多线程 print('waiting for connection..') tcpServ.serve_forever()
练习:(以下答案个人理解不保证正确)
1.套接字。面向连接的套接字和无连接套接字之间的区别是什么?
面向连接 是指进行通讯之前必须建立一个连接,又称为虚拟电路或流套接字。 通讯提供序列化的、可靠的和不重复的数据交付。二没有记录边界 主要协议是传输控制协议(TCP)无连接 是指通讯之前不需要建立连接。数据报类型套接字 传输过程中无法保证他的顺序性、可靠性或重复性。然而数据报确实保存了记录边界 主要协议是用户数据报协议(UDP)
2.客户端/服务器架构.用自己的话描述这个术语的意思,并给出几个例子
人们通过客户端从服务器端获取想要的内容消费者和24小时商店的关系,消费者可以随时去进行消费,商店就相当于服务器,一直在等待着人们去消费。
3.套接字。TCP和UDP之中,哪种类型的服务器接受连接,并将他们转换到独立的套接字进行客户端通信?
UDP
4.客户端。更新TCP(tsTclnt.py)以使得服务器名称无需硬编码到应用程序中。此外,应该允许用户指定主机名和端口号,且如果二者中任何一个或者全部参数丢失,那么应该使用默认值
from socket import *def sock(HOST, PORT): BUFSIZ = 1024 ADDR = (HOST, PORT) print(ADDR) tcpCliSock = socket(AF_INET, SOCK_STREAM) tcpCliSock.connect(ADDR) while True: data = input('<<:') if not data: print('输入为空!') continue tcpCliSock.send(data.encode('utf-8')) data = tcpCliSock.recv(BUFSIZ) if not data: print('服务器端异常') break print(data.decode()) tcpCliSock.close()if __name__ == '__main__': HOST = input('主机名<<:') PORT = input('端口号<<:') if not HOST : HOST = 'localhost' if not PORT: PORT = 9999 sock(HOST,PORT)
5.半双工聊天。创建一个简单的半双工聊天程序。指定半双工,我们呢的意思就是,当建立一个连接且服务开始后,只有一个人能打字,而另一个参与者在得到输入消息提示之前必须等待消息。并且,一旦发送者发送了一条消息,在他能够再次发送消息之前,必须等待对方回复,其中,一个参与者将在服务器一侧,而另一位在客户端一侧。
'''服务器端'''import socketHOST = ''PORT = 9999BUFSIZ = 1024ADDR = (HOST, PORT)server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(ADDR)server.listen()while True: tcpClientSock, addr = server.accept() print('...connected from:', addr) while True: data = tcpClientSock.recv(BUFSIZ) if not data: print('not data') break print('recv:', data.decode()) sends = input('<<:') if not sends: continue tcpClientSock.send(sends.encode('utf-8')) tcpClientSock.close()server.close()
'''客户端'''import socketHOST = 'localhost'PORT = 9999BUFSIZ = 1024ADDR = (HOST, PORT)client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)client.connect(ADDR)while True: data = input('<<:') if not data: continue client.send(data.encode('utf-8')) serverdata = client.recv(BUFSIZ) if not serverdata: print('服务器端无返回') break print(serverdata.decode())client.close()
- socket
- socket
- Socket
- Socket
- Socket
- Socket
- Socket
- Socket
- socket
- Socket
- Socket
- Socket
- Socket
- socket
- socket
- socket
- socket
- socket
- Unit10 更多结构化命令
- android studio中如何重命名文件
- 数据集
- H5 2D渲染引擎—Pixi.js 精灵的位置、大小、旋转、移动
- selinux-概览
- socket
- 信息安全笔记(一)
- 第23讲项目5-我的加班费
- 九度[1005]-Graduate Admission
- 计算机内存和缓存
- C# 索引器的使用
- 机器学习(一)基本概念与信息熵
- C
- Redis为什么使用单进程单线程方式也这么快