Python進階三部曲網絡編程

使用Python進行網絡編程時,其實是在Python程序中自己這個進程內,鏈接到指定服務器進程的通訊端口進行通訊,因此網絡通訊也能夠當作兩個進程間的通訊。java

提到網絡編程必須提到的一個概念是Socket,Socket是網絡編程的一個抽象概念,一般咱們用一個Socket表示打開了一個網絡鏈接,而打開一個socket須要知道目標計算機的IP地址和端口號,再指定協類型便可。python

Python提供了兩個基本的Socket模塊:android

  1. 提供了標準的BSD Sockets API
  2. SocketServer,提供了服務器中心類,能夠簡化網絡服務器的開發。

Socket類型。

套接字格式爲:socket(family,type[,protocal]),使用給定的地鐵,套接字類型,協議編號(默認爲0)來建立套接字。編程

Socket類型及說明。服務器

Socket類型 描述
socket.AF_UNIX 只可以用於單一的Unix系統進程問通訊
socket.AF_INET 服務器之間網絡通訊
socket.AF_INET6 IPv6
socket.SOCK_STREAM 流式socket,用TCP
socket.SOCK_DGRAM 教據報式socket,用於UDP
socket.SOCK_RAW 原始套接字,普通的套接字沒法處理ICMP、IGMP等網絡報文,而SOCK_RAW 能夠; 其次,SOCK_RAW 也能夠處理特殊的IPV4報文; 此外,利用原始套接字,能夠經過IP_HDRINCL 套接字選項由用戶構造IP頭
socket.SOCK_SEOPACKET 可靠的連續數據包服務
建立TCP Socket s=socket socket( socket.AF_INET,socket SOCK_STREAM)
建立UDP Socket s=socket.socket(socket.AF_INET,socket SOCK_DGRAM

Socket函數

Socket函數及說明。網絡

Socket函數 描述
- 服務端函數
s.bind(address) 將套接字綁定到地址,在AFINET下,以元組Chost.port) 的形式表示地址
s.listen( backlog ) 開始監聽TCP傳人連按。backlog指定在拒絕鏈接以前,操做系統能夠掛起的最大鏈接數量。該值至少爲1,大部分應用程序設爲5就能夠了
s.accept() 接受TCP鏈接開返回(conn,addes ),其中conn 是新的套接字對象,能夠用來接收和發送數據。address是鏈接客戶端的地址
- 客戶端Socket函數
s connect(address ) 鏈接到 address 處的套接字。通常 address 的格式爲元組(hostoame,port ),若是鏈接出錯,返回socket.error 錯誤
s.connect_ex(adddress) 功能與conncct(address)相同,可是成功返回0,失敗返同ermno 的值
- 公共Socket函數
s.recv bufsize[,flag) 接受TCP 套接字的數據。數據以字符串形式返回,bufsize 指定要接收的最大數據量。flag提供有關消息的其餘信息,一般能夠忽略
s.send(stringC,flag]) 發送TCP數據。將string中的數據發送到鏈接的套接字。返回值是要發送的字節數量,該數量可能小於string 的字節大小
s.sendall(string[,flag]) 完整發送TCP 數據。將string 中的數據發送到鏈接的套接字,但在返同以前會嘗試發送全部數據。成功返回None,失敗則拋出異常
s.recvfrom(bufsize[.flag]) 接受UDP 套接字的數據。與recv0相似,但返回值是data,addres )。其中data 是包含接收數據的字符串,address是發送數據的套接字地址
s.sendto(string[,flag].address) 發送UDP 數據。將數據發送到套接字,address 是形式爲(ipaddr.port) 的元組,指定遠程地址。返回值是發送的字節數
s.close() 關閉套接字
s.getpeername() 返回鏈接套接字的遠程地址。返回值一般是元組(ipaddr.port)
s.getsockname() 返回套接字自 己的地址。一般是一個元組(ipadd.port)
s.setsockopt(level,optname,value) 設置給定套接字選項的值
s.getsockopt(level,optname[.buflen]) 返回套接字選項的值
s.settimeout(timeout) 設置套接字操做的超時期,timcout 是一個浮點數,單位是秒。值爲None 表示沒有超時期。通常超時期應該在剛建立套接字時設置,由於它們可能會用於鏈接操做(如connect())
s.setblocking(flag) 若是fag 爲0,則將套接字設爲非阻塞模式,不然將套接字設爲阻塞模式( 默認值)。非阻塞模式下,若是調用recv()沒有發現任何數據,或send()調用沒法當即發送數據,將引發socket.error異常

TCP編程

網絡編程通常包括肉部分:服務器和客戶端,TCP是一種面向鏈接的通訊方式,主動發起鏈接的叫客戶端,被動響應的鏈接叫服務器。併發

建立服務端:

首先說一下服務器,建立和運行服務端通常須要5個步驟:socket

  1. 建立Socket,綁定Socket到本地IP與端口。
  2. 開始監聽鏈接
  3. 進入循環,不斷接收客戶的鏈接請求
  4. 接收傳來的數據,併發送給對方數據。
  5. 傳輸完畢後,關閉Socket.
# coding:utf-8
import socket
import threading
import time

def dealClient(sock, addr):
    # 接收傳來的數據,併發送給對方數據。
    print('Accpet new conn from %s:%s' % addr)
    sock.send(b'hello, i am server')
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        if not data or data.decode('utf-8') == 'exit':
            break
        print('%s!' % data.decode('utf-8'))
        sock.send(('Loop_msg:%s!' % data.decode('utf-8')).encode('utf-8'))
    # 關閉socket
    sock.close()
    print('conn from %s:%s close.' % addr)

if __name__ == "__main__":
    # 第一步:建立一個基於IPV4和TCP協議的Socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # socket綁定IP(127.0.0.1爲本機IP)與端口。
    s.bind(('127.0.0.1', 9999))
    # 監聽鏈接。
    s.listen(5)

    print('wating for conn...')

    while True:
        # 接收一個新鏈接,
        sock, addr = s.accept()
        # 建立新線程來處理TCP鏈接。
        t = threading.Thread(target=dealClient, args=(sock, addr))
        t.start()

建立客戶端:

  1. 建立Socket,鏈接遠端地址。
  2. 鏈接後發送數據和接收數據。
  3. 傳輸完畢後,關閉Socket
import socket

# 初始化Socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 鏈接目標的IP和端口。
s.connect(('127.0.0.1', 9999))
# 接收數據,
print('-->>', s.recv(1024).decode('utf-8'))
# 發送數據。
s.send(b'Hello,i am a client')
print('-->>' + s.recv(1024).decode('utf-8'))
s.send(b'exit')
# 關閉socket
s.close()

先運行,服務端,再運行客戶端,獲得:
-->> hello, i am server
-->>Loop_msg:Hello,i am a client!

UDP編程,

TCP通訊須要一個創建可靠鏈接的過程,並且通訊雙方以流的形式發送數據。相對TCP,UDP則是面向無鏈接的協議,使用UDP協議時,不須要創建鏈接,只須要知道對方的IP地址和端口號,就能夠直接發送數據包,可是不關心是否能到達目的端,雖然使用UDP傳輸數據不可靠,但因爲它沒有創建鏈接的過程,速度比TCP快得多,對於不要求可靠到達的數據,就可使用UDP協議。ide

使用UDP協議,TCP同樣,也有服務端與客房端之分,UDP編程相對於TCP編程比較簡單,服務端建立和運行只須要3個步驟:函數

  1. 建立Socket,綁定指定的IP和端口。
  2. 直接發送數據和接收數據,
  3. 關閉Socket

建立服務端:

# coding:utf-8
import socket

# 建立Socket,綁定指定的IP和端口。
# SOCK_DGRAM 指定了這個Socket的類型是UDP,綁定端品和TCP示例同樣。
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 9999))
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)

建立客戶端

建立Socket,直接能夠與服務端進行數據交互換。

# coding:utf-8
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in [b'hello', b'world',b'python',b'android',b'java']:
    # 發送數據
    s.sendto(data, ('127.0.0.1', 9999))
    # 接收數據,
    print(s.recv(1024).decode('utf-8'))

s.close()

獲得:
hello,hello!
hello,world!
hello,python!
hello,android!
hello,java!

以上就是UDP服務端和客房端數據交互的流程,UDP的使用與TCP類型,可是不須要創建鏈接,此外,服務器綁定UDP端口和TCP端口互不衝突,即UDP的9999端品與TCP的9999端口能夠各自綁定。

相關文章
相關標籤/搜索