python网络编程

简介

网络编程就是在程序中实现网络中两台计算机的通信。而用Python进行网络编程,就是在Python程序本身这个进程内,连接别的服务器进程的通信端口进行通信。

初识Socket

Socket(又称套接字)起源于Unix,是应用层与TCP/IP协议族通信的中间软件抽象层。复杂的TCP/IP协议族隐藏在了Socket接口内部,用户只需要简单地使用Socket接口来进行网络编程。应用程序通常是通过Socket向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

创建Socket
在Python中,我们用 socket()函数来创建套接字,语法格式如下:
-> socket(family,type[,protocol])
参数解释:

family:socket家族描述
socket.AF_UNIX只能够用于单一的Unix系统进程间通信
socket.AF_INET指定使用IPv4协议进行服务器间网络通信
socket.AF_INET6指定使用IPv6协议进行服务器间网络通信
type:socket类型描述
socket.SOCK_STREAM流式socket , for TCP
socket.SOCK_DGRAM数据报式socket , for UDP
socket.SOCK_RAW原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
socket.SOCK_SEQPACKET可靠的连续数据包服务
protocol:socket协议描述
一般不填且默认为0系统会根据地址格式和套接字类别,自动选择一个合适的协议。

Socket常用方法

服务器端方法描述
socket.bind(address)绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。
socket.listen(backlog)开始监听TCP传入连接。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
socket.accept()被动接受TCP客户端连接并返回(sock,address),其中sock是新的套接字对象,可以用来接收和发送数据,address是连接客户端的地址。
客户端方法描述
socket.connect(address)主动初始化TCP服务器连接,一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
socket.connect_ex(address)connect()的扩展版本,出错时返回出错码,而不是抛出异常。
公共方法描述
socket.recv(bufsize[,flag])接受TCP套接字的数据。数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
socket.send(string[,flag])发送TCP数据。将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。
socket.sendall(string[,flag])完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
socket.recvfrom(bufsize[.flag])接受UDP套接字的数据。与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
socket.sendto(string[,flag],address)发送UDP数据。将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。
socket.close()关闭套接字。

TCP编程

大多数网络通信连接都是可靠的TCP连接。创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器;连接成功后,通信双方都能以流的形式发送数据。

在Python中用TCP协议进行Socket编程十分简单,对于客户端,要主动连接服务器的IP和指定端口,对于服务器,要首先监听指定端口,然后,对每一个新的连接,创建一个线程或进程来处理。通常,服务器程序会无限运行下去。要注意的是,一个端口不能同被两个Socket绑定。

下图展示了TCP服务端和客户端各自Socket创建以及它们之间的交互过程:
这里写图片描述

接下来是一个简单的示例程序(建议自己敲下来跑一遍),服务器端接收客户端的连接请求,把客户端发过来的字符串加上Hello再发回去。

服务器端代码:

#!/usr/bin/python
# 文件名:tcp_server.py

import socket
import threading
import time

# 实现连接成功后的交互,参数sock为套接字对象,addr为客户端地址
def tcplink(sock, addr):
    # 输出连接成功的提示:
    print('Accept new connection from %s:%s...' % addr)
    # 发送TCP数据:
    sock.send(b'Hello, What\'s your name?') 
    while True:
        # 接收小于 1024 字节的数据
        data = sock.recv(1024) 
        time.sleep(1)
        if not data or data.decode('utf-8') == 'disconnect':
            break
        sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
    # 关闭Socket,一次完整的网络通信就此结束
    sock.close()
    print('Connection from %s:%s closed.' % addr)

# 创建一个基于IPv4和TCP协议的socket:    
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定地址(host,port)到套接字:
s.bind(('127.0.0.1', 9999))
# 开始监听,最大连接数设为5:
s.listen(5)

print('TCP Server is running...')    
print('Waiting for connection...')    
while True:
    # 被动接受TCP客户端连接,(阻塞式)等待连接的到来:
    sock, addr = s.accept()
    # 创建新线程来处理TCP连接:
    t = threading.Thread(target=tcplink, args=(sock, addr))
    t.start()

客户端代码:

#!/usr/bin/python
# 文件名:tcp_client.py

import socket

# 创建一个基于IPv4和TCP协议的socket:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接,指定主机和端口:
s.connect(('127.0.0.1', 9999))
# 接收欢迎消息:
print(s.recv(1024).decode('utf-8'))

# 持续与服务器交互:
while True:
    # 获取用户输入:
    msg = input('Your input:')
    if not msg or msg == 'quit':
        break
    # 发送数据:
    s.send(msg.encode('utf-8'))
    # 输出服务器返回的消息
    print('From server:',s.recv(1024).decode('utf-8'))

# 发送断开连接的指令    
s.send(b'disconnect')
# 套接字关闭
s.close()

打开三个命令行窗口,一个运行服务器端程序,另外两个运行客户端程序,效果如下图:
这里写图片描述

UDP编程

相对TCP,UDP则是面向无连接的协议。使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就可以直接发数据包。但是,数据包能否到达是无法确定的。

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

接下来我们使用UDP协议来实现与上面示例的程序。

服务器端代码:

#!/usr/bin/python
# 文件名:udp_server.py

import socket

# 创建一个基于IPv4和UDP协议的socket:    
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定地址(host,port)到套接字:
s.bind(('127.0.0.1', 9999))

print('UDP Server is running...')
print('Waiting for message...')  
while True:
    # 接收数据,recvfrom()方法返回数据和客户端的地址与端口:
    data, addr = s.recvfrom(1024)
    print('Received from %s:%s.' % addr)
    s.sendto(b'Hello, %s!' % data, addr)

客户端代码:

#!/usr/bin/python
# 文件名:udp_client.py

import socket

# 创建一个基于IPv4和UDP协议的socket:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 持续与服务器交互:
while True:
    # 获取用户输入
    msg = input('Your input:')
    if not msg or msg == 'quit':
        break
    # 无需连接,直接发送数据到服务器Socket绑定的地址:
    s.sendto(msg.encode('utf-8'), ('127.0.0.1', 9999))
    # 输出服务器返回的消息:
    print('From server:',s.recv(1024).decode('utf-8'))

# 套接字关闭
s.close()

打开三个命令行窗口,一个运行服务器端程序,另外两个运行客户端程序,效果如下图:
这里写图片描述


参考文章:
- python socket编程
- 菜鸟教程-python3网络编程
- 廖雪峰-python3教程

  • 11
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值