socket

socket—–套接字基础

创建socket

import socket
tcpsock = 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 socket

ss = 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 ctime

HOST = 'localhost'
PORT = 9999
BUFSIZ = 1024
ADDR = (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 = 9999
BUFSIZ = 1024
ADDR = (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/ThreadingUDPServerThreadingMixIn 和 TCPServer/UDPServer的组合
BaseRequestHandler包含处理服务器请求的核心功能;仅仅用于推导,这样无法创建这个类的实例;可以用StreamRequestHandler 或 DatagramRequestHandler 创建类的实例
StreamRequestHandler/DatagramRequestHandler实现Tcp/UDP服务器的服务处理器

用socketserver实现tsTserv.py

from socketserver import (TCPServer as TCP,
                          StreamRequestHandler as SRH)

from time import ctime

HOST = ''
PORT = 9999
ADDR = (HOST, PORT)
BUFSIZ = 1024

class 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 = 9999
BUFSIZ = 1024
ADDR = (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 ctime

HOST = ''
PORT = 9999
ADDR = (HOST, PORT)
BUFSIZ = 1024

class 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 socket

HOST = ''
PORT = 9999
BUFSIZ = 1024
ADDR = (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 socket

HOST = 'localhost'
PORT = 9999
BUFSIZ = 1024
ADDR = (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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值