python實現TCP/UDP通訊

一.說明

對於TCP/udp的說明已經不少了,我在這裏只是簡單的說明一下python

二.套接字scoket

 套接字是一種具備以前所說的「通訊端點」概念的計算網絡數據結構。至關

於電話插口,沒它沒法通訊,這個比喻很是形象。
        套接字起源於20世紀70年代加州伯克利分校版本的Unix,即BSD Unix

。又稱爲「伯克利套接字」或「BSD套接字」。最初套接字被設計用在同一臺

主機上多個應用程序之間的通信,這被稱爲進程間通信或IPC。
        套接字分兩種:基於文件型和基於網絡的
        第一個套接字家族爲AF_UNIX,表示「地址家族:UNIX」。包括

Python在內的大多數流行平臺上都使用術語「地址家族」及其縮寫AF。因爲兩

個進程都運行在同一臺機器上,並且這些套接字是基於文件的,因此它們的底

層結構是由文件系統來支持的。能夠理解爲同一臺電腦上,文件系統確實是不

同的進程都能進行訪問的。
        第二個套接字家族爲AF_INET,表示」地址家族:Internet「。還有

一種地址家族AF_INET6被用於網際協議IPv6尋址。Python 2.5中加入了一種

Linux套接字的支持:AF_NETLINK(無鏈接)套接字家族,讓用戶代碼與內核

代碼之間的IPC可使用標準BSD套接字接口,這種方法更爲精巧和安全。
        Python只支持AF_UNIX、AF_NETLINK和AF_INET家族。網絡編程關注

AF_INET。
        若是把套接字比做電話的查看——即通訊的最底層結構,那主機與端

口就至關於區號和電話號碼的一對組合。一個因特網地址由網絡通訊必須的主

機與端口組成。
        並且另外一端必定要有人接聽才行,不然會提示」對不起,您撥打的電

話是空號,請查詢後再撥「。一樣你也可能會遇到如」不能鏈接該服務器、服

務器沒法響應「等。合法的端口範圍是0~65535,其中小於1024端口號爲系統

保留端口。編程

三.面向鏈接與無鏈接

 面向鏈接:通訊以前必定要創建一條鏈接,這種通訊方式也被成爲」虛電路

「或」流套接字「。面向鏈接的通訊方式提供了順序的、可靠地、不會重複的

數據傳輸,並且也不會被加上數據邊界。這意味着,每發送一份信息,可能會

被拆分紅多份,每份都會很少很多地正確到達目的地,而後從新按順序拼裝起

來,傳給正等待的應用程序。
        實現這種鏈接的主要協議就是傳輸控制協議TCP。要建立TCP套接字就

得建立時指定套接字類型爲SOCK_STREAM。TCP套接字這個類型表示它做爲流套

接字的特色。因爲這些套接字使用網際協議IP來查找網絡中的主機,因此這樣

造成的整個系統,通常會由這兩個協議(TCP和IP)組合描述,即TCP/IP。
        無鏈接:無需創建鏈接就能夠通信。但此時,數據到達的順序、可靠

性及不重複性就沒法保障了。數據報會保留數據邊界,這就表示數據是整個發

送的,不會像面向鏈接的協議先拆分紅小塊。它就至關於郵政服務同樣,郵件

和包裹不必定按照發送順序達到,有的甚至可能根本到達不到。並且網絡中的

報文可能會重複發送。
        那麼這麼多缺點,爲何還要使用它呢?因爲面向鏈接套接字要提供

一些保證,須要維護虛電路鏈接,這都是嚴重的額外負擔。數據報沒有這些負

擔,全部它會更」便宜「,一般能提供更好的性能,更適合某些場合,如現場

直播要求的實時數據講究快等。
        實現這種鏈接的主要協議是用戶數據報協議UDP。要建立UDP套接字就

得建立時指定套接字類型爲SOCK_DGRAM。這個名字源於datagram(數據報),

這些套接字使用網際協議來查找網絡主機,整個系統叫UDP/IP。 安全

四.socket()模塊函數

  使用socket模塊的socket()函數來建立套接字。語法以下:
            socket(socket_family, socket_type, protocol=0)
        其中socket_family不是AF_VNIX就是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 socket import *"語

句,把socket模塊裏面的全部屬性都帶到命名空間中,大幅縮短代碼。調用如

下:
             tcpSock = socket(AF_INET, SOCK_STREAM)服務器

 

五.套接字對象

下面是最經常使用的套接字對象方法:
       服務器端套接字函數網絡

socket類型數據結構

描述socket

s.bind()tcp

綁定地址(主機號 端口號對)到套接字函數

s.listen()性能

開始TCP監聽

s.accept()

被動接受TCP客戶端鏈接,(阻塞式)等待連續的到來

       客戶端套接字函數

socket類型

描述

s.connect()

主動初始化TCP服務器鏈接

s.connect_ex()

connect()函數擴展版本,出錯時返回出錯碼而不是跑出異常

       公共用途的套接字函數

socket類型

描述

s.recv()

接受TCP數據

s.send()

發送TCP數據

s.sendall()

完整發送TCP數據

s.recvfrom()

接受UDP數據

s.sendto()

發送UDP數據

s.getpeername()

鏈接到當前套接字的遠端地址(TCP鏈接)

s.getsockname()

獲取當前套接字的地址

s.getsockopt()

返回指定套接字的參數

s.setsockopt()

設置指定套接字的參數

s.close()

關閉套接字

        面向模塊的套接字函數

socket類型

描述

s.setblocking()

設置套接字的阻塞與非阻塞模式

s.settimeout()

設置阻塞套接字操做的超時時間

s.gettimeout()

獲得阻塞套接字操做的超時時間

        面向文件的套接字函數

 

socket類型

描述

s.fileno()

套接字的文件描述符

s.makefile()

建立一個與套接字關聯的文件對象

六.代碼實現

 TCP服務端代碼

#! /usr/bin/env python
#coding=utf-8
import socket
bind_ip = ""
bind_port = 9999

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

server.bind((bind_ip,bind_port))

server.listen(5)
try:
        while True:
                client,add = server.accept()
                print "[*]你監聽的是:%s:%d" % (add[0],add[1])
                while True:
                        data = client.recv(1024)
                        if not data:
                                break
                        print data
                        data = raw_input('> ')
                        client.send(data)
#                       print data
                else:
                        client.close()
except Exception as e:
        print e
server.close()

TCP客戶端代碼

#! /usr/bin/env python
#coding=utf-8

import socket

target_host = "127.0.0.1"
target_port = 9999

#創建一個socket對象
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#連接客戶端
client.connect((target_host,target_port))


while True:
        data = raw_input('> ')
        client.send(data)
    
        #發送一些數據
        #client.send("GET /HTTP/1.1\r\nHost:baidu.com\r\n\r\n")
        data = client.recv(4096)
        if not data:
                break
        print data

 

UDP服務端

# -*- coding: utf-8 -*- 
from socket import *
from time import ctime

HOST = ''                   #主機名
PORT =  21567               #端口號
BUFSIZE = 1024              #緩衝區大小1K
ADDR = (HOST,PORT)

udpSerSock = socket(AF_INET, SOCK_DGRAM)
udpSerSock.bind(ADDR)       #綁定地址到套接字

while True:                 #無限循環等待鏈接到來
    try:
        print 'Waiting for message ....'
        data, addr = udpSerSock.recvfrom(BUFSIZE)          #接受UDP
        print 'Get client msg is: ', data
        udpSerSock.sendto('[%s] %s' %(ctime(),data), addr) #發送UDP
        print 'Received from and returned to: ',addr

    except Exception,e:
        print 'Error: ',e
udpSerSock.close()          #關閉服務器

UDP服務端

# -*- coding: utf-8 -*- 
from socket import *

HOST = 'localhost'          #主機名
PORT =  21567               #端口號 與服務器一致
BUFSIZE = 1024              #緩衝區大小1K
ADDR = (HOST,PORT)

udpCliSock = socket(AF_INET, SOCK_DGRAM)

while True:                 #無限循環等待鏈接到來
    try:
        data = raw_input('>')
        if not data:
            break
        udpCliSock.sendto(data, ADDR)            #發送數據
        data,ADDR = udpCliSock.recvfrom(BUFSIZE)  #接受數據
        if not data:
            break
        print 'Server : ', data

    except Exception,e:
        print 'Error: ',e
        
udpCliSock.close()          #關閉客戶端
相關文章
相關標籤/搜索