Python研究学习--10--网络编程

版权声明:本文为博主原创文章,转载本站文章请注明作者和出处,请勿用于任何商业用途。 https://blog.csdn.net/wutianxu123/article/details/82527853

10.1 理论基础

客户端/服务器架构:
服务器开放,客户端访问服务器的数据
注意!在任何客户端与服务器连接之前,都要首先启动服务器,后启动客户端。

套接字(socket):
源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字
1、没有任何类型的通信开始之前,网络应用必须创建套接字
2、用于同一主机上进程与进程之间的通信
3、用于网络中一个主机与另一个主机之间的通信。通信(套接字)地址:(主机名:端口)

面向连接的套接字:通信之前必须先建立连接。协议为TCP。套接字类型为:SOCK_STREAM
无连接的套接字:通信之前不需要建立连接。协议为UDP。套接字类型为:SOCK_DGRAM

模块:socket

import socket
from socket import *

函数:socket

socket.socket()      #socket模块下的socket函数。用于创建套接字对象

-------------------------------------------------------------------------------------

函数的语法格式:
socket(socket_family, socket_type, protocol=0)

函数解释:
socket_family: 套接字家族可以使AF_UNIX或者AF_INET
socket_type:   套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
protocol:      一般不填默认为0

常见的套接字对象方法及属性
服务器套接字:

方法 解释
s.bind() 绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址
s.listen() 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
s.accept() 被动接受TCP客户端连接,(阻塞式)等待连接的到来

客户端套接字:

方法 解释
s.connect() 主动初始化TCP服务器连接。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数:(客户端和服务器都可用)

方法 解释
s.recv() 接收 TCP 消息
s.recv_into() 接收 TCP 消息到指定的缓冲区
s.send() 发送 TCP 消息
s.sendall() 完整地发送 TCP 消息
s.recvfrom() 接收 UDP 消息
s.recvfrom_into() 接收 UDP 消息到指定的缓冲区
s.sendto() 发送 UDP 消息
s.getpeername() 连接到套接字(TCP)的远程地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回给定套接字选项的值
s.setsockopt() 设置给定套接字选项的值
s.shutdown() 关闭连接
s.close() 关闭套接字
s.detach() 在未关闭文件描述符的情况下关闭套接字,返回文件描述符
s.ioctl() 控制套接字的模式

面向阻塞的套接字方法:

方法 解释
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间

面向文件的套接字函数:

方法 解释
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间

数据属性:

扫描二维码关注公众号,回复: 3101476 查看本文章
方法 解释
s.family() 套接字家族
s.type 套接字类型
s.proto 套接字协议

10.2 TCP通信

面向连接的套接字

创建TCP套接字,必须使用SOCK_STREAM作为套接字类型。

TCP服务器伪代码:

ss=socket()                     #创建服务器套接字,即将其赋予某变量
ss.bind()                       #套接字与地址绑定。服务器需要占用一个端口并等待客户端连接,因此必须绑定到一个本地地址
ss.listen()                     #监听连接。现在我们是创建TCP服务器,所以需要监听
inf_loop:                       #服务器无限循环,等待客户端接入
    cs=ss.accept()              #accept开启一个单线程服务器,接受客户端的连接
    comm_loop:                  #通信循环,客户端与服务端的通信数据流
        cs.recv()/cs.send()     #对话。接收/发送
    cs.close()                  #关闭客户端套接字。断开与客户端的连接
ss.close()                      #(不会用到!)关闭服务端套接字。服务器断开与所有的连接

TCP客户端伪代码:

cs=socket()                     #创建客户端套接字,将其赋予某变量
cs.connect()                    #尝试连接服务器。就如输入服务器地址一样
comm_loop:                      #通信循环
    cs.send()/cs.recv()         #对话。发送/接收
cs.close()                      #关闭客户端套接字。就如关闭浏览器一样

TCP通信实例一:上方为服务器代码,下方为客户端代码。下同

# -*- coding: UTF-8 -*-
# 服务器代码段
import socket                                       #导入socket模块

s = socket.socket()                                 #创建socket对象
host = socket.gethostname()                         #获取本地主机名
port = 12345                                        #设置端口
s.bind((host, port))                                #将套接字绑定到服务器地址。服务器地址为:本机IP:12345

s.listen(5)                                         #等待客户端连接。开启TCP监听
while True:
    c, addr = s.accept()                            #建立并接受客户端连接。注意前面是两个参数。因为客户端传送了两个数据
    print u'连接地址:', addr                         #连接地址为客户端地址
    c.send(u'欢迎访问我们'.encode('gb2312'))          #发送给客户端的数据
    c.close()                                       #关闭客户端套接字

-------------------------------------------------------------------------------------

# -*- coding: UTF-8 -*-
# 客户端代码段
import socket                           #导入socket模块

s = socket.socket()                     #创建socket对象
host = socket.gethostname()             #获取本地主机名(服务器地址)
port = 12345                            #设置端口号(服务器端口) 

s.connect((host, port))                 #尝试连接服务器,括号中为服务器地址
print s.recv(1024)                      #对话。接收服务器返回的数据。括号中为缓存大小
s.close()                               #关闭客户端套接字

TCP通信实例二

# -*- coding: UTF-8 -*-
#服务器代码段

from socket import *                    #导入socket模块
from time import ctime                  #导入time模块

host=""                                 #服务器地址。为空代表可以是任何可用的地址,实验可用地址为本地地址(127.0.0.1/localhost)
port=1234                               #服务器端口。没有被占用即可
huancun=1024                            #设置缓存。该应用程序为1kb
addr=(host,port)                        #组成服务器的可访问地址

tcpfuwu=socket(AF_INET,SOCK_STREAM)     #创建socket对象
tcpfuwu.bind(addr)                      #将套接字绑定到服务器地址(绑定后地址存在并可连)
tcpfuwu.listen(5)                       #开启TCP监听,连接在被转接或拒绝之前,传入连接请求的最大数为5

while True:
    print u"玩命加载中请耐心等待……"        #连接请求出现时即显示
    tcpkehu,addr=tcpfuwu.accept()       #建立并接受客户端连接。此处是单线程连接
    print u"连接来自于:",addr             #输出自定义数据

    while True:
        data=tcpkehu.recv(huancun)      #接收客户端传回的数据,不超过缓存大小,超出则服务端奔溃,客户端显示乱码!
        if not data:                    #如果接收数据为空则退出循环,后果是关闭客户端
            break
        tcpkehu.send('[%s]%s'%(ctime(),data))      #向客户端发送数据。[时间戳]客户端输入的数据

    tcpkehu.close()                     #关闭客户端
tcpfuwu.close()                         #这条代码永不执行。关闭服务端

-------------------------------------------------------------------------------------

# -*- coding: UTF-8 -*-
#客户端代码段
from socket import *

host="127.0.0.1"                        #服务器地址
port=1234                               #服务器端口
huancun=1024                            #应用程序缓存。1kb
addr=(host,port)                        #组合成服务器地址

tcpkehu=socket(AF_INET,SOCK_STREAM)     #创建socket对象
tcpkehu.connect(addr)                   #连接服务器。括号中为服务器地址

while True:
    data=raw_input('>')                 #一种显示规则。接收键盘输入数据
    if not data:                        #如果输入数据为空,跳出循环。后果是客户端套接字关闭
        break
    tcpkehu.send(data)                  #将输入的数据发送给服务器
    data=tcpkehu.recv(huancun)          #服务器调用recv函数,用于给客户端返回数据
    if not data:                        #如果服务器终止且调用recv函数失败则跳出循环。后果是客户端套接字关闭
        break
    print data                          #输出服务器返回给客户端的数据
tcpkehu.close()                         #关闭客户端套接字

10.3 UDP通信

不需要TCP服务器那么多设置,因为它不是面向连接的
创建UDP套接字,必须使用SOCK_DGRAM作为套接字类型

UDP服务器伪代码:

ss=socket()                             #创建服务器套接字,即将其赋予某变量
ss.bind()                               #套接字与地址绑定
inf_loop:                               #服务器无限循环,等待客户端接入
    cs=ss.recvfrom()/ss.sendto()        #对话。接收/发送
ss.close()                              #(不会用到!)关闭服务器套接字

UDP客户端伪代码:

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

UDP通信实例:

# -*- coding: UTF-8 -*-
#服务器代码段

from socket import *
from time import ctime

host=""
port=1234
huancun=1024
addr=(host,port)

udpfuwu=socket(AF_INET,SOCK_DGRAM)
udpfuwu.bind(addr)                                      #注意!UDP不用调用监听传入连接(listen)

while True:
    print u"玩命加载中请稍后……"
    udpkehu,addr=udpfuwu.recvfrom(huancun)              #接收客户端传来的数据。客户端发送两个数据给服务器,服务器就需要两个变量来接收。
    udpfuwu.sendto('[%s]%s'%(ctime(),udpkehu),addr)     #发送数据给客户端
    print u"来自连接:",addr
udpfuwu.close()

-------------------------------------------------------------------------------------

# -*- coding: UTF-8 -*-
#客户端代码段
from socket import *

host="localhost"
port=1234
huancun=1024
addr=(host,port)

udpkehu=socket(AF_INET,SOCK_DGRAM)

while True:
    data=raw_input(">")
    if not data:
        break
    udpkehu.sendto(data,addr)                 #将输入的数据发送给服务器
    data,addr=udpkehu.recvfrom(huancun)       #前面的两个变量可以和服务器的不一样。因为我们只在客户端使用,而服务器的这两个变量我们只在服务器上使用
    if not data:                              #如果服务器终止且调用recv函数失败则跳出循环
        break
    print data
udpkehu.close()

10.4 socket模块属性

数据类型:

方法 解释
AF_UNIX、AF_INET、AF_INET6、AF_NETLINK、AF_TIPC Python支持的套接字地址家族
SO_STREAM、SO_DGRAM 套接字类型 (TCP =流, UDP =数据报)
has_ipv6 表示是否支持 IPv6 的布尔标记

异常:

方法 解释
error 套接字相关错误
herror 主机和地址相关的错误
gaierror 地址相关的错误
timeout 超时

常见函数:

方法 解释
socket() 用指定的地址家族,套接字类型和协议类型(可选)创建一个套接字对象
socketpair() 用指定的地址家族,套接字类型和协议类型(可选)创建一对套接字对象
create_connection() 常规函数,它接收一个地址(主机名,端口号)对,返回套接字对象
fromfd() 用一个已经打开的文件描述符创建一个套接字对象
ssl() 通过套接字启动一个安全套接字层(SSL)连接;不做证书验证
getaddrinfo() 获取一个五元组序列形式的地址消息
getnameinfo() 给定一个套接字地址,返回(主机名,端口号)二元组
getfqdn() 返回完整的域名
gethostname() 返回当前主机名
gethostbyname() 将一个主机名映射到它的IP地址

猜你喜欢

转载自blog.csdn.net/wutianxu123/article/details/82527853