Python网络编程之socket

1. 简单的图解socket流程

2.  连接原理

根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。

(1)服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

(2)客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

(3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接 字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

3.1.  案例服务端

# -*- coding:utf8 -*-
import socket
import sys

HOST = '127.0.0.1'
PORT = 8005

# python之socket模块
def s_server():
    s = None
    l_data = socket.getaddrinfo(
        HOST,
        PORT,
        socket.AF_UNSPEC,
        socket.SOCK_STREAM,
        0,
        socket.AI_PASSIVE
    )
    for res in l_data:
        af, socketype, proto, canonname, sa = res
        try:
            s = socket.socket(af, socketype, proto)
        except socket.error as msg:
            s = None
            continue
        try:
            s.bind(sa)
            s.listen(5)
        except socket.error as msg:
            s.close()
            s = None
            continue
        break
    if s is None:
        print 'could not open socket'
        sys.exit()
    return s

if __name__ == '__main__':
    s = s_server()
    conn, addr = s.accept()
    print 'Connected by', addr
    while True:
        data = conn.recv(1024)  #  接收客户端发送的数据
        if not data:
            break
        conn.send(data) #发送数据到客户端
    conn.close()

getaddrinfo函数源码:

def getaddrinfo(host, port, family=None, socktype=None, proto=None, flags=None): # real signature unknown; restored from __doc__
    """
    getaddrinfo(host, port [, family, socktype, proto, flags])
        -> list of (family, socktype, proto, canonname, sockaddr)
    Resolve host and port into addrinfo struct.
    """
    return []

参数:family(地址簇类型)

socket.AF_UNIX 用与单一机器下的进程通信
socket.AF_INET 用与服务器之间相互通信,通常都用这个。
socket.AF_INET6 支持IPv6
参数:sockettype(socket类型) 常用的有以下几种
socket.SOCK_STREAM 默认,用于TCP协议
socket.SOCK_DGRAM 用于UDP协议
参数:proto (协议)
getaddrinnfo函数会根据地址格式和socket类型,返回合适的协议

返回值:canonname

是一个规范化的host name

返回值:sockaddr

是一个二元组,主要用于bind()和connect()函数, 

参数:0(默认)

与特定的地址家族相关的协议,如果是0, 则系统就会根据地址格式和套接类别,自动选择一个合适的协议

创建socket对象:

s = socket.socket(af, socketype, proto)

绑定socket address:

s.bind(sa)

开启监听:

s.listen(5)

注意:listen函数会监听连接到socket上的连接,参数表示在拒绝连接之前系统可以挂起的最大连接队列数量为5。这些连接还没有被accept处理。数量不能无限大,通常指定5

收到监听调用accept函数接收连接

conn, addr = s.accept()

注意:accept函数返回一个二元组,conn是一个新的socket对象,用来接收和发送数据。addr表示另一端的socket地址。

conn对象发送和接收数据:

while True:
        data = conn.recv(1024)  #  接收客户端发送的数据
        if not data:
            break
        conn.send(data) #发送数据到客户端
注意:接收到一个连接socket就会停止运行,所以如果要循环连接的话,将accept函数放入到一个死循环里。


3.2.  案例客户端

# -*- coding:utf8 -*-
import socket
import sys

# python之socket模块
HOST = '127.0.0.1'
PORT = 8005
def s_client():
    s = None
    l_data = socket.getaddrinfo(
        HOST,
        PORT,
        socket.AF_UNSPEC,
        socket.SOCK_STREAM
    )
    for res in l_data:
        af, socketype, proto, canonname, sa = res
        try:
            s = socket.socket(af, socketype, proto)
        except socket.error as msg:
            s = None
            continue
        try:
            s.connect(sa)
        except socket.error as msg:
            s.close()
            s = None
            continue
        break
    if s is None:
        print 'could not open socket'
        sys.exit(1)
    return s
s = s_client()
s.sendall('Hello world!')
data = s.recv(1024)
s.close()
print 'Received', repr(data)

注意:通过connect和服务端建立连接之后,就可以相互通信了

特别注意:以上主要是针对TCP流数据的socket编程。对于UDP协议的数据,处理略有不同。

譬如发送接收UDP数据包处理函数为:

socket.sendto(string, flags, address)
socket.recvfrom(bufsize[, flags]) 
# 返回(string, address)  
# string是返回的数据,address是发送方的socket地

注意:详细的TCP与UDP的区别请在详细的查一查,后续我会添加上


注意:以上内容是个人使用的随手记录, 就是介绍了下简单的使用

欢迎大家来吐槽,准备好瓜子饮料矿泉水,开整!!!

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


搞笑一则:能动手尽量别吵吵



注意:以上内容是个人使用的随手记录, 就是介绍了下简单的使用

欢迎大家来吐槽,准备好瓜子饮料矿泉水,开整!!!

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值