001-网络编程

套接字:通信端点。

有两种类型的套接字:基于文件的和面向网络的。

AF:address family,地址家族
STREAM:流
DGRAM:datagram,数据报

1、面向连接的套接字

面向连接的通信提供序列化的、可靠的和不重复的数据交付,而没有记录边界。这基本上意味着每条消息可以拆分成多个片段,并且每一条消息片段都确保能够到达目的地,然后将它们按顺序组合在一起,最后将完整消息传递给正在等待的应用程序。

实现这种连接类型的主要协议是传输控制协议(更为人熟知的是它的缩写 TCP)。为了创建 TCP 套接字,必须使用 SOCK_STREAM 作为套接字类型。TCP 套接字的名字 SOCK_STREAM 基于流套接字的其中一种表示。因为这些套接字(AF_INET)的网络版本使用因特网协议(IP)来搜寻网络中的主机,所以整个系统通常结合这两种协议(TCP 和 IP)来进行(当然,也可以使用 TCP 和本地[非网络的 AF_LOCAL/AF_UNIX]套接字,但是很明显此时并没有使用 IP)。

2、无连接的套接字

与虚拟电路形成鲜明对比的是数据报类型的套接字,它是一种无连接的套接字。这意味着,在通信开始之前并不需要建立连接。此时,在数据传输过程中并无法保证它的顺序性、可靠性或重复性。然而,数据报确实保存了记录边界,这就意味着消息是以整体发送的,而并非首先分成多个片段,例如,使用面向连接的协议。

既然有这么多副作用,为什么还使用数据报呢(使用流套接字肯定有一些优势)?由于面向连接的套接字所提供的保证,因此它们的设置以及对虚拟电路连接的维护需要大量的开销。然而,数据报不需要这些开销,即它的成本更加“低廉”。因此,它们通常能提供更好的性能,并且可能适合一些类型的应用程序。

实现这种连接类型的主要协议是用户数据报协议(更为人熟知的是其缩写 UDP)。为 了创建 UDP 套接字,必须使用 SOCK_DGRAM 作为套接字类型。你可能知道,UDP 套接字的 SOCK_DGRAM 名字来自于单词“datagram”(数据报)。因为这些套接字也使用因特网协议来寻找网络中的主机,所以这个系统也有一个更加普通的名字,即这两种协议(UDP 和 IP)的组合名字,或 UDP/IP。

3、socket 网络编程

3.1 创建套接字

socket.socket(socket_family, socket_type, proto=0)

  • socket_family:AF_UNIX/AF_LOCAL(本地套接字) 或 AF_INET/AF_INET6(基于IP的套接字)
      AF_LOCAL 将代替 AF_UNIX,然而考虑到向后兼容性,很多系统都同时使用二者。
      注意:目前 python 只支持 AF_UNIX
  • socket_type:SOCK_STREAM(TCP) 或 SOCK_DGRAM(UDP)
  • proto:通常省略,默认为0
# 创建 TCP/IP 套接字
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 创建 UDP/IP 套接字
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

3.2 套接字对象(内置)方法

在这里插入图片描述
在这里插入图片描述

3.3 TCP 编程

1) 创建 TCP 服务器

ss = socket()   # 创建服务器套接字
ss.bind()       # 套接字与地址绑定
ss.listen()     # 监听连接
inf_loop:       # 服务器无限循环
    cs = ss.accept()    # 接受客户端连接,该方法会阻塞
    comm_loop:          # 通信循环
        cs.recv()/cs.send()     # 对话(接收 / 发送)
    cs.close()  # 关闭客户端套接字
ss.close()      # 关闭服务器套接字 # (可选)

服务器代码:

from socket import *

HOST = 'localhost'
PORT = 21567
BUFSIZE = 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(f'...connected from: {addr}')
    print('----------------------')

    while True:
        client_data = tcpCliSock.recv(BUFSIZE)
        print(f'Clinet: {client_data.decode("utf-8")}')
        if not client_data:
            break
        server_data = input('Server: ')
        tcpCliSock.send(server_data.encode('utf-8'))

    tcpCliSock.close()
tcpSerSock.close()

2) 创建 TCP 客户端

cs = socket()   # 创建客户端套接字
cs.connect()    # 尝试连接服务器
comm_loop:      # 通信循环
    cs.send()/cs.recv()     # 对话(发送 / 接收)
cs.close()      # 关闭客户端套接字

客户端代码:

from socket import *

HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)

tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)

while True:
    client_data = input('Clinet > ')
    if not client_data:
        break

    tcpCliSock.send(client_data.encode('utf-8'))
    server_data = tcpCliSock.recv(BUFSIZE)
    if not server_data:
        break
    print(f'Server > {server_data.decode("utf-8")}')
tcpCliSock.close()

3)执行 TCP 服务端和客户端

执行 TCP 服务端和客户端后,客户端和服务端就可以进行通信了。

3.4 UDP 编程

1)创建 UDP 服务器

ss = socket()   # 创建服务器套接字
ss.bind()       # 绑定服务器套接字
inf_loop:       # 服务器无限循环
    cs = ss.recvfrom()/ss.sendto()  # 关闭(接收 / 发送)
ss.close()      # 关闭服务器套接字

服务器端代码:

from socket import *

HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)

udpSerSock = socket(AF_INET, SOCK_DGRAM)
udpSerSock.bind(ADDR)

print('waiting for message...')
print('-------------------')
while True:
    client_data, addr = udpSerSock.recvfrom(BUFSIZE)
    print(f'Clinet: {client_data.decode("utf-8")}')
    server_data = input('Server: ')
    udpSerSock.sendto(server_data.encode('utf-8'), addr)

udpSerSock.close()

2)创建 UDP 客户端

cs = socket()   # 创建客户端套接字
comm_loop:      # 通信循环
    cs.sendto()/cs.recvfrom()   # 对话(发送 / 接收)
cs.close()      # 关闭客户端套接字

客户端代码:

from socket import *

HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)

udpCliSock = socket(AF_INET, SOCK_DGRAM)

while True:
    client_data = input('Clinet > ')
    if not client_data:
        break

    udpCliSock.sendto(client_data.encode('utf-8'), ADDR)
    server_data, addr = udpCliSock.recvfrom(BUFSIZE)
    if not server_data:
        break
    print(f'Server > {server_data.decode("utf-8")}')
    
udpCliSock.close()

3)执行 UDP 服务端和客户端

执行 UDP 服务端和客户端后,客户端和服务端就可以进行通信了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值