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套接字

内置方法

名称 描述 服务器套接字方法 s.bind() s.listen() s.accept() 客户端套接字方法 s.connect() s.connect_ex() 普通的套接字方法 s.recv() s.recv_into() s.send() s.sendall() s.recvfrom() s.recvfrom_into() s.sendto() s.getpeername() s.getsockname() s.getsockopt() s.setsockopt() s.shutdown() s.close() s.detach() s.ioctl() 面向阻塞的套接字方法 s.setblocking() s.settimeout() s.gettimeout() 面向文件的套接字方法 s.fileno() s.makefile() 数据属性 s.family s.type s.proto

创建一个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模块类

类 描述 BaseServer 包含核心服务器功能和 mix-in类的钩子;仅用于推导,这样不会创建这个类的实例;可以用TCPServer 或 UDPServer 创建类的实例 TCPServer/UDPServer 基础的网络同步TCP/UDP服务器 UnixStreamServer/UnixDatagramServer 基于文件的基础同步TCp/UDP服务器 ForkingMixIn/ThreadingMixIn 核心派出或线程功能;只用做mix-in类与一个服务器类配合实现一些异步性;不能直接实例化这个类 ThreadingTCPServer/ThreadingUDPServer ThreadingMixIn 和 TCPServer/UDPServer的组合 BaseRequestHandler 包含处理服务器请求的核心功能;仅仅用于推导,这样无法创建这个类的实例;可以用StreamRequestHandler 或 DatagramRequestHandler 创建类的实例 StreamRequestHandler/DatagramRequestHandler 实现Tcp/UDP服务器的服务处理器

用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()
原创粉丝点击