10.python網路編程(startin part 1)

來源:互聯網
上載者:User

標籤:python   tcp   socket   udp   

一.什麼是socket?

socket就是為了實現C/S架構而生的,socket位於應用程式層和傳輸層之間,是傳輸層和應用程式層之間的一組介面,它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,一組簡單的介面就是全部,讓Socket去組織資料,以符合指定的協議,所以,我們無需深入理解tcp/udp協議,socket已經為我們封裝好了,我們只需要遵循socket的規定去編程,寫出的程式自然就是遵循tcp/udp標準的。

也有人將socket說成ip+port,ip是用來標識互連網中的一台主機的位置,而port是用來標識這台機器上的一個應用程式,ip地址是配置到網卡上的,而port是應用程式開啟的,ip與port的綁定就標識了互連網中獨一無二的一個應用程式。

補充:有人會把socket和程式的pid弄混,程式的pid是同一台機器上不同進程或者線程的標識。


二.socket種類。

  1. 基於檔案型通訊端。

    AF_UNIX:基於檔案型的通訊端,就是通過底層的檔案系統來取資料,兩個通訊端進程運行在同一台機器,可以通過訪問同一個檔案系統來實現兩個程式之間的通訊。

  2. 基於網路型通訊端。

三.socket工作流程。

650) this.width=650;" src="http://images.cnblogs.com/cnblogs_com/goodcandle/socket3.jpg" width="478" height="491" hspace="0" />

tcp服務端建立串連流程:

socket()執行個體化出一個通訊端對象→bind()綁定ip地址和連接埠→listen()開始監聽之前綁定的ip地址和連接埠→accept()開始被動接收tcp用戶端發來的串連,會一直等串連的到來(如果沒有串連,就會一直等,直到有用戶端連過來。

tcp用戶端建立串連流程:

socket()用戶端也初始化一個通訊端對象→connect()主動去串連服務端(主動初始化與tcp伺服器的串連)如果串連成功,用戶端和伺服器之間就可以互相收發資料了。(其實connect就相當於去回應服務端的accept,服務端的accept一直在等待用戶端去connect)

用戶端發送資料請求,伺服器端接收請求並處理請求,然後把回應資料發送給用戶端,用戶端讀取資料,最後關閉串連,一次互動結束。



四.socket模組的用法。

import socket

socket.socket(socket_family,socket_type,protocal=0)

socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,預設值為 0。

擷取tcp/ip通訊端

tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

擷取udp/ip通訊端

udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

由於 socket 模組中有太多的屬性。我們在這裡破例使用了‘from module import *‘語句。使用 ‘from socket import *‘,我們就把 socket 模組裡的所有屬性都帶到我們的命名空間裡了,這樣能 大幅減短我們的代碼。

例如tcpSock = socket(AF_INET, SOCK_STREAM)


服務端常用專屬通訊端方法:

s.bind():綁定(主機,連接埠號碼)到通訊端。

s.listen():開始進行tcp監聽。#listen方法中可以指定一個backlog參數,這個參數用於設定tcp串連池的大小(關於tcp串連池和三向交握的知識後面會做補充。)

s.accept():被動接受TCP客戶的串連,(阻塞式)等待串連的到來。


用戶端常用專屬通訊端方法:

s.connect():主動初始化TCP伺服器串連

s.connect_ex() : connect()函數的擴充版本,出錯時返回出錯碼,而不是拋出異常。


用戶端和服務端共同具有的常用通訊端方法:

s.recv():接收tcp資料。#需要指定每次收多少位元組。

s.send():  發送tcp資料,#發送TCP資料(send在待發送資料量大於對端緩衝區剩餘空間時,資料丟失,不會發完)

s.sendall(): 發送tcp資料,發送完整的TCP資料(本質就是迴圈調用send,sendall在待發送資料量大於對端緩衝區剩餘空間時,資料不丟失,迴圈調用send直到發完)(個人分析,本質上是調用了迴圈)

s.recvfrom():接收UDP資料

s.sendto() : 發送UDP資料

s.getpeername() : 串連到當前通訊端的遠端的地址

s.getsockname()  :   當前通訊端的地址

s.getsockopt() :返回指定通訊端的參數

s.setsockopt() : 設定指定通訊端的參數

s.close() :關閉通訊端


五.socket用法樣本。

服務端:

#!/usr/bin/python2.7

# -*- coding:utf-8 -*-

import socket

address_and_port = (‘127.0.0.1‘,8888)

s1 = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

s1.bind(address_and_port)

s1.listen(3)

conn,addr = s1.accept() #執行了socket的accept方法後,開始阻塞,等待用戶端的串連.

#執行了accept方法後,會返回一個元祖,這個元祖裡麵包含了一個用戶端的連線物件,還有用戶端的ip地址和連接埠.

while True:

    data = conn.recv(1024) #用於接收tcp資料,後面的1024表示,recv一次最多可以接收1024位元組.(執行到recv,如果對端沒有發來資料,或者內容為空白,程式會阻塞住,不繼續向下執行。)

    print data

    conn.send(data.upper())

conn.close() #關閉與用戶端的串連

s1.close()  #關閉服務端通訊端串連


用戶端:

#!/usr/bin/python2.7

# -*- coding:utf-8 -*-

import socket

s1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s1.connect((‘127.0.0.1‘,8888))

while True:

    msg = raw_input(">>>").strip()

    s1.send(msg.encode((‘utf-8‘)))

    print "用戶端已發送資料!"

    data = s1.recv(1024)

    print data

#上面兩個代碼,可以簡單理解下socket的工作流程。


六.解決sockt 通訊用戶端斷開服務端崩潰等問題的解決方案(串連迴圈,通訊迴圈,以及異常捕捉)

服務端:

#!/usr/bin/python2.7

# -*- coding:utf-8 -*-

import socket

address_and_port = (‘127.0.0.1‘,8888)

s1 = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

s1.bind(address_and_port)

s1.listen(3)

while True:  #此處問串連迴圈,會迴圈等串連。

    conn,addr = s1.accept() #執行了socket的accept方法後,開始阻塞,等待用戶端的串連.

        #執行了accept方法後,會返回一個元祖,這個元祖裡麵包含了一個用戶端的連線物件,還有用戶端的ip地址和連接埠.

    while True:  #資料轉送迴圈

        try:    #防止用戶端斷開導致的服務斷拋異常。

            data = conn.recv(1024) #用於接收tcp資料,後面的1024表示,recv一次最多可以接收1024位元組.

            if not data:

                break

            print data

            conn.send(data.upper())

        except Exception:

            break

conn.close() #關閉與用戶端的串連

s1.close()  #關閉服務端通訊端串連


用戶端:

#!/usr/bin/python2.7

# -*- coding:utf-8 -*-

import socket

s1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s1.connect((‘127.0.0.1‘,8888))

while True:

    msg = raw_input(">>>").strip()

    if not msg:  #防止用戶端發送空資料

        continue

    s1.send(msg.encode((‘utf-8‘)))

    print "用戶端已發送資料!"

    data = s1.recv(1024)

    print data

s1.close()


#以上是防止服務端崩潰的一些解決方案。






七.關於udp通訊端。

服務端大概操作流程:

ss = socket()   #建立一個伺服器的通訊端

ss.bind()       #綁定伺服器通訊端

inf_loop:       #伺服器無限迴圈

cs = ss.recvfrom()/ss.sendto() # 對話(接收與發送)

ss.close()                         # 關閉伺服器通訊端



用戶端大概的操作流程:

cs = socket()   # 建立客戶通訊端

comm_loop:      # 通訊迴圈

    cs.sendto()/cs.recvfrom()   # 對話(發送/接收)

cs.close()                      # 關閉客戶通訊端


下面是udp通訊端的一個簡單的樣本:

 樣本1:

服務端:

import socket

udp_server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

udp_server.bind((‘127.0.0.1‘,8888))

while True:

    msg,addr = udp_server.recvfrom(1024)

    print msg ,addr

    udp_server.sendto(msg.upper(),addr)


用戶端:

import socket

udp_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

while True:

    msg = raw_input(">>:").strip()

    if not msg:

        continue

    udp_client.sendto(msg.encode(‘utf-8‘),("127.0.0.1",8888))

    back_msg,addr = udp_client.recvfrom(1024)

    print back_msg.decode(‘utf-8‘) ,addr



八.關於tcp通訊端和udp通訊端你需要知道的。

  1. 首先有幾點必須明確!

    1.1  所有的收發訊息,都是在操作自己的tcp/udp緩衝區,發訊息是將資料發送到自己的緩衝區中,收訊息同樣也是從緩衝區中收取。

    1.2 tcp 使用send發訊息,使用recv收訊息

    1.3udp 使用sendto發訊息,使用recvfrom收訊息

  2. tcp與udp

    2.1 tcp是基於流的,udp是基於報的

2.2 使用send發送資料流的時候,若資料流為空白,那麼tcp buffer(緩衝區)也為空白,作業系統不會控制tcp發包。

sendinto(bytes_data,ip_port):發送資料報,bytes_data為空白,還有ip_port,所有即便是發送空的bytes_data,資料報其實也不是空的,自己這端的緩衝區收到內容,作業系統就會控制udp協議發包。

3.關於tcp的補充

tcp基於連結通訊:

    基於連結,則需要listen(backlog),指定半串連池的大小

    基於連結,必須先啟動並執行服務端,然後用戶端發起連結請求

    對於mac系統:如果一端斷開了連結,那另外一端的連結也跟著完蛋recv將不會阻塞,收到的是空(解        決方法是:服務端在收訊息後加上if判斷,空訊息就break掉通訊迴圈)

    對於windows/linux系統:如果一端斷開了連結,那另外一端的連結也跟著完蛋recv將不會阻塞,收到        的是空(解決方案是:服務端通訊迴圈內加異常處理,捕捉到異常後就break掉通訊迴圈)


udp通訊。

無連結,因而無需listen(backlog),更加沒有什麼串連池之說了

無連結,udp的sendinto不用管是否有一個正在啟動並執行服務端,可以己端一個勁的發訊息,只不過資料丟失

recvfrom收的資料小於sendinto發送的資料時,在mac和linux系統上資料直接丟失,在windows系統上發送的比接收的大直接報錯

只有sendinto發送資料沒有recvfrom收資料,資料丟失。


注意:

1.你單獨運行上面的udp的用戶端,你發現並不會報錯,相反tcp卻會報錯,因為udp協議只負責把包發出去,對方收不收,我根本不管,而tcp是基於連結的,必須有一個服務端先運行著,用戶端去跟服務端建立連結然後依託於連結才能傳遞訊息,任何一方試圖把連結摧毀都會導致對方程式的崩潰。

2.上面的udp程式,你注釋任何一條用戶端的sendinto,服務端都會卡住,為什嗎?因為服務端有幾個recvfrom就要對應幾個sendinto,哪怕是sendinto(b‘‘)那也要有。


本文出自 “reBiRTH” 部落格,請務必保留此出處http://suhaozhi.blog.51cto.com/7272298/1922917

10.python網路編程(startin part 1)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.