Python学习之网络编程

Python学习目录python

  1. 在Mac下使用Python3
  2. Python学习之数据类型
  3. Python学习之函数
  4. Python学习之高级特性
  5. Python学习之函数式编程
  6. Python学习之模块
  7. Python学习之面向对象编程
  8. Python学习之面向对象高级编程
  9. Python学习之错误调试和测试
  10. Python学习之IO编程
  11. Python学习之进程和线程
  12. Python学习之正则
  13. Python学习之经常使用模块
  14. Python学习之网络编程

互联网的实现,分红好几层。每一层都有本身的功能,就像建筑物同样,每一层都靠下一层支持。如何分层有不一样的模型,有的模型分七层,有的分四层。我以为,把互联网分红五层,比较容易解释。最底下的一层叫作"实体层"(Physical Layer),最上面的一层叫作"应用层"(Application Layer),中间的三层(自下而上)分别是"连接层"(Link Layer)、"网络层"(Network Layer)和"传输层"(Transport Layer)。越下面的层,越靠近硬件;越上面的层,越靠近用户。编程

网络编程

TCP编程

Socket是网络编程的一个抽象概念。一般咱们用一个Socket表示“打开了一个网络连接”,而打开一个Socket须要知道目标计算机的IP地址和端口号,再指定协议类型便可。服务器

客户端

建立Socket

# 导入socket库:
import socket

# 建立一个socket:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 创建链接:
s.connect(('www.sina.com.cn', 80))
复制代码

建立Socket时,AF_INET指定使用IPv4协议,若是要用更先进的IPv6,就指定为AF_INET6SOCK_STREAM指定使用面向流的TCP协议,这样,一个Socket对象就建立成功,可是尚未创建链接。网络

链接服务器

s.connect(('www.sina.com.cn', 80))
复制代码

注意参数是一个tuple,包含地址和端口号。多线程

发送请求

# 发送数据:
s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')
复制代码

TCP链接建立的是双向通道,双方均可以同时给对方发数据。可是谁先发谁后发,怎么协调,要根据具体的协议来决定。例如,HTTP协议规定客户端必须先发请求给服务器,服务器收到后才发数据给客户端。app

接收数据

# 接收数据:
buffer = []
while True:
    # 每次最多接收1k字节:
    d = s.recv(1024)
    if d:
        buffer.append(d)
    else:
        break
data = b''.join(buffer)
复制代码

关闭Socket

# 接收数据:
buffer = []
while True:
    # 每次最多接收1k字节:
    d = s.recv(1024)
    if d:
        buffer.append(d)
    else:
        break
data = b''.join(buffer)
复制代码

服务器

建立Socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
复制代码

建立一个基于IPv4和TCP协议的Socket。socket

绑定监听的地址和端口

# 监听端口:
s.bind(('127.0.0.1', 9999))
s.listen(5)
print('Waiting for connection...')
复制代码

listen()方法传入的参数指定等待链接的最大数量。tcp

接受客户端链接

while True:
    # 接受一个新链接:
    sock, addr = s.accept()
    # 建立新线程来处理TCP链接:
    t = threading.Thread(target=tcplink, args=(sock, addr))
    t.start()
复制代码

每一个链接都必须建立新线程(或进程)来处理,不然,单线程在处理链接的过程当中,没法接受其余客户端的链接:函数式编程

def tcplink(sock, addr):
    print('Accept new connection from %s:%s...' % addr)
    sock.send(b'Welcome!')
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        if not data or data.decode('utf-8') == 'exit':
            break
        sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
    sock.close()
    print('Connection from %s:%s closed.' % addr)
复制代码

UDP编程

TCP是创建可靠链接,而且通讯双方均可以以流的形式发送数据。相对TCP,UDP则是面向无链接的协议。函数

使用UDP协议时,不须要创建链接,只须要知道对方的IP地址和端口号,就能够直接发数据包。可是,能不能到达就不知道了。

虽然用UDP传输数据不可靠,但它的优势是和TCP比,速度快,对于不要求可靠到达的数据,就能够使用UDP协议。

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定端口:
s.bind(('127.0.0.1', 9999))
复制代码

建立Socket时,SOCK_DGRAM指定了这个Socket的类型是UDP。绑定端口和TCP同样,可是不须要调用listen()方法,而是直接接收来自任何客户端的数据:

print('Bind UDP on 9999...')
while True:
    # 接收数据:
    data, addr = s.recvfrom(1024)
    print('Received from %s:%s.' % addr)
    s.sendto(b'Hello, %s!' % data, addr)
复制代码

recvfrom()方法返回数据和客户端的地址与端口,这样,服务器收到数据后,直接调用sendto()就能够把数据用UDP发给客户端。

注意这里省掉了多线程,由于这个例子很简单。

客户端使用UDP时,首先仍然建立基于UDP的Socket,而后,不须要调用connect(),直接经过sendto()给服务器发数据:

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in [b'Michael', b'Tracy', b'Sarah']:
    # 发送数据:
    s.sendto(data, ('127.0.0.1', 9999))
    # 接收数据:
    print(s.recv(1024).decode('utf-8'))
s.close()
复制代码

从服务器接收数据仍然调用recv()方法。

相关文章
相关标签/搜索