Python Socket 網絡編程

2022-01-10 python

 

TCP 是一種面向連接的傳輸層協議,TCP Socket 是基於一種 Client-Server 的編程模型,服務端監聽客戶端的連接請求,一旦建立連接即可以進行傳輸數據。那麼對 TCP Socket 編程的介紹也分為客戶端和服務端:

客戶端編程創建 socket

首先要創建 socket,用 Python 中 socket 模塊的函數 socket 就可以完成:

 import socket   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print 'Socket Created'

函數 socket.socket 創建一個 socket,返回該 socket 的描述符,將在後面相關函數中使用。該函數帶有兩個參數:

註:由於本文主要概述一下 Python Socket 編程的過程,因此不會對相關函數參數、返回值進行詳細介紹,需要了解的可以查看相關手冊

錯誤處理

如果創建 socket 函數失敗,會拋出一個 socket.error 的異常,需要捕獲:

 import socket  import sys   try:        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)except socket.error, msg:    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]    sys.exit(); print 'Socket Created'

那麼到目前為止已成功創建了 socket,接下來我們將用這個 socket 來連接某個伺服器,就連 www.google.com 吧。

連接伺服器

本文開始也提到了,socket 使用 (IP位址,協議,埠號) 來標識一個進程,那麼我們要想和伺服器進行通信,就需要知道它的 IP位址以及埠號。

獲得遠程主機的 IP 地址

Python 提供了一個簡單的函數 socket.gethostbyname 來獲得遠程主機的 IP 地址:

host = 'www.google.com'port = 80 try:    remote_ip = socket.gethostbyname( host ) except socket.gaierror:        print 'Hostname could not be resolved. Exiting'    sys.exit() print 'Ip address of ' + host + ' is ' + remote_ip

現在我們知道了伺服器的 IP 地址,就可以使用連接函數 connect 連接到該 IP 的某個特定的埠上了,下面例子連接到 80 埠上(是 HTTP 服務的默認埠):

s.connect((remote_ip , port)) print 'Socket Connected to ' + host + ' on ip ' + remote_ip

運行該程序:

$ pythonclient.pySocket createdIpofremotehostwww.google.comis 173.194.38.145Socket Connectedtowww.google.comonip 173.194.38.145

發送數據

上面說明連接到 www.google.com 已經成功了,接下面我們可以向伺服器發送一些數據,例如發送字符串 GET / HTTP/1.1rnrn ,這是一個 HTTP 請求網頁內容的命令。

message = "GET / HTTP/1.1rnrn" try :        s.sendall(message)except socket.error:        print 'Send failed'    sys.exit() print 'Message send successfully'

發送完數據之後,客戶端還需要接受伺服器的響應。

接收數據

函數 recv 可以用來接收 socket 的數據:

reply = s.recv(4096) print reply

一起運行的結果如下:

Socket createdIpofremotehostwww.google.comis 173.194.38.145Socket Connectedtowww.google.comonip 173.194.38.145MessagesendsuccessfullyHTTP/1.1 302 FoundCache-Control: privateContent-Type: text/html; charset=UTF-8Location: http://www.google.com.sg/?gfe_rd=cr&ei=PlqJVLCREovW8gfF0oG4CQContent-Length: 262Date: Thu, 11 Dec 2014 08:47:58 GMTServer: GFE/2.0Alternate-Protocol: 80:quic,p=0.02 <HTML><HEAD><metahttp-equiv="content-type" content="text/html;charset=utf-8"><TITLE>302 Moved</TITLE></HEAD><BODY><H1>302 Moved</H1>Thedocumenthasmoved<A HREF="http://www.google.com.sg/?gfe_rd=cr&ei=PlqJVLCREovW8gfF0oG4CQ">here</A>.</BODY></HTML>

關閉 socket

當我們不想再次請求伺服器數據時,可以將該 socket 關閉,結束這次通信:

s.close()

小結

上面我們學到了如何:

創建 socket

連接到遠程伺服器

發送數據

接收數據

關閉 socket

當我們打開 www.google.com 時,瀏覽器所做的就是這些,知道這些是非常有意義的。在 socket 中具有這種行為特徵的被稱為 CLIENT ,客戶端主要是連接遠程系統獲取數據。

socket 中另一種行為稱為 SERVER ,伺服器使用 socket 來接收連接以及提供數據,和客戶端正好相反。所以 www.google.com 是伺服器,你的瀏覽器是客戶端,或者更準確地說,www.google.com 是 HTTP 伺服器,你的瀏覽器是 HTTP 客戶端。

那麼上面介紹了客戶端的編程,現在輪到伺服器端如果使用 socket 了。

伺服器端編程

伺服器端主要做以下工作:

打開 socket

綁定到特定的地址以及埠上

監聽連接

建立連接

接收/發送數據

上面已經介紹了如何創建 socket 了,下面一步是綁定。

綁定 socket

函數 bind 可以用來將 socket 綁定到特定的地址和埠上,它需要一個 sockaddr_in 結構作為參數:

import socketimport sys HOST = ''  PORT = 8888  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)print 'Socket created' try:    s.bind((HOST, PORT))except socket.error , msg:    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]    sys.exit() print 'Socket bind complete'

綁定完成之後,接下來就是監聽連接了。

監聽連接

函數 listen 可以將 socket 置於監聽模式:

s.listen(10)print 'Socket now listening'

該函數帶有一個參數稱為 backlog ,用來控制連接的個數。如果設為 10,那麼有 10 個連接正在等待處理,此時第 11 個請求過來時將會被拒絕。

接收連接

當有客戶端向伺服器發送連接請求時,伺服器會接收連接:

conn, addr = s.accept() print 'Connected with ' + addr[0] + ':' + str(addr[1])

運行該程序的,輸出結果如下:

$ pythonserver.pySocket createdSocket bindcompleteSocket nowlistening

此時,該程序在 8888 埠上等待請求的到來。不要關掉這個程序,讓它一直運行,現在客戶端可以通過該埠連接到 socket。我們用 telnet 客戶端來測試,打開一個終端,輸入 telnet localhost 8888 :

$ telnetlocalhost 8888Trying 127.0.0.1...Connectedtolocalhost.Escapecharacteris '^]'.Connectionclosedbyforeignhost.

這時服務端輸出會顯示:

$ pythonserver.pySocket createdSocket bindcompleteSocket nowlisteningConnectedwith 127.0.0.1:59954

我們觀察到客戶端已經連接上伺服器了。在建立連接之後,我們可以用來與客戶端進行通信。下面例子演示的是,伺服器建立連接之後,接收客戶端發送來的數據,並立即將數據發送回去,下面是完整的服務端程序:

import socketimport sys HOST = ''  PORT = 8888  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)print 'Socket created' try:    s.bind((HOST, PORT))except socket.error , msg:    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]    sys.exit() print 'Socket bind complete' s.listen(10)print 'Socket now listening' conn, addr = s.accept() print 'Connected with ' + addr[0] + ':' + str(addr[1]) data = conn.recv(1024)conn.sendall(data) conn.close()s.close()

在一個終端中運行這個程序,打開另一個終端,使用 telnet 連接伺服器,隨便輸入字符串,你會看到:

$ telnetlocalhost 8888Trying 127.0.0.1...Connectedtolocalhost.Escapecharacteris '^]'.happyhappyConnectionclosedbyforeignhost.

客戶端(telnet)接收了伺服器的響應。

我們在完成一次響應之後伺服器立即斷開了連接,而像 www.google.com 這樣的伺服器總是一直等待接收連接的。我們需要將上面的伺服器程序改造成一直運行,最簡單的辦法是將 accept 放到一個循環中,那麼就可以一直接收連接了。

保持服務

我們可以將代碼改成這樣讓伺服器一直工作:

import socketimport sys HOST = ''  PORT = 5000  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)print 'Socket created' try:    s.bind((HOST, PORT))except socket.error , msg:    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]    sys.exit() print 'Socket bind complete' s.listen(10)print 'Socket now listening' while 1:        conn, addr = s.accept()    print 'Connected with ' + addr[0] + ':' + str(addr[1])     data = conn.recv(1024)    reply = 'OK...' + data    if not data:         break     conn.sendall(reply) conn.close()s.close()

現在在一個終端下運行上面的伺服器程序,再開啟三個終端,分別用 telnet 去連接,如果一個終端連接之後不輸入數據其他終端是沒辦法進行連接的,而且每個終端只能服務一次就斷開連接。這從代碼上也是可以看出來的。

這顯然也不是我們想要的,我們希望多個客戶端可以隨時建立連接,而且每個客戶端可以跟伺服器進行多次通信,這該怎麼修改呢?

處理連接

為了處理每個連接,我們需要將處理的程序與主程序的接收連接分開。一種方法可以使用線程來實現,主服務程序接收連接,創建一個線程來處理該連接的通信,然後伺服器回到接收其他連接的邏輯上來。

import socketimport sysfrom thread import * HOST = ''  PORT = 8888  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)print 'Socket created' try:    s.bind((HOST, PORT))except socket.error , msg:    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]    sys.exit() print 'Socket bind complete' s.listen(10)print 'Socket now listening' def clientthread(conn):        conn.send('Welcome to the server. Type something and hit entern')          while True:                 data = conn.recv(1024)        reply = 'OK...' + data        if not data:             break         conn.sendall(reply)         conn.close() while 1:        conn, addr = s.accept()    print 'Connected with ' + addr[0] + ':' + str(addr[1])         start_new_thread(clientthread ,(conn,)) s.close()

再次運行上面的程序,打開三個終端來與主伺服器建立 telnet 連接,這時候三個客戶端可以隨時接入,而且每個客戶端可以與主伺服器進行多次通信。

telnet 終端下可能輸出如下:

$ telnetlocalhost 8888Trying 127.0.0.1...Connectedtolocalhost.Escapecharacteris '^]'.Welcometotheserver. Type somethingand hitenterhiOK...hiasdOK...asdcvOK...cv

要結束 telnet 的連接,按下 Ctrl-] 鍵,再輸入 close 命令。

伺服器終端的輸出可能是這樣的:

$ pythonserver.pySocket createdSocket bindcompleteSocket nowlisteningConnectedwith 127.0.0.1:60730Connectedwith 127.0.0.1:60731

python學習資料交流群:516107834  每天會更新視頻資料,可以隨便下載。

相關焦點

  • Python入門基礎之socket多線程編程,TCP伺服器和客戶端通信
    在上一篇文章中,我介紹了一下python3 socket編程的基礎,包括TCP、UDP客戶端和伺服器的建立過程(連結在最下方)。不過那個只是單線程的,伺服器一次只能和一個客戶端會話,多個客戶端的話只能等待。我們平時的應用中,伺服器肯定是要並發的,所以,今天將介紹socket編程的多線程編程。
  • python socket實戰(二)
    這個在c語言編程中尤為常見。例如,有一個如下到結構體,python如何用socket進行通信傳遞該消息呢。的網絡編程。"下表是常見到python類型、字節和格式符號到對應表。、IGMP等網絡報文,而SOCK_RAW可以;其次,SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始套接字,可以通過IP_HDRINCL套接字選項由用戶構造IP頭。
  • 我開始學Python網絡編程了
    最近在和小夥伴們一起搞事情,我是學統計出身,編程能力其實很差,有點拖後腿了。所以需要惡補基礎,這個系列會更新幾篇,感興趣的同學可以一起學習交流。ZeroMQ概述ZeroMQ(又名ØMQ,MQ,或zmq)像一個可嵌入的網絡庫,但其作用就像一個並發框架。ZeroMQ類似於標準Berkeley套接字,其提供了各種傳輸工具,如進程內、進程間、TCP和組播中進行原子消息傳送的套接字。
  • 從socket到TCP協議,透徹理解網絡編程
    進行程序開發的同學,無論Web前端開發、Web後端開發,還是搜尋引擎和大數據,幾乎所有的開發領域都會涉及到網絡編程。比如我們進行Web服務端開發,除了Web協議本身依賴網絡外,通常還需要連接資料庫,而資料庫連接通常是通過網絡連接資料庫伺服器,或者資料庫集群,如果負載太高還要搞個緩存集群。我們在上學的時候基本學了網絡編程和網絡協議。
  • python socket編程
    else:        if (proto == "http"):            port = 80        elif (proto == "https"):            port = 443    host = dest[0]        if (proto == "http"):        sock = socket.socket
  • 簡單說說Python Socket編程步驟?
    廢話不多說,開始今天的題目:問:簡單說說Python socket編程步驟?答:Socket是應用層與TCP/IP協議族通信的中間軟體抽象層,它是一組接口。所以,我們無需深入理解tcp/udp協議,socket已經為我們封裝好了,我們只需要遵循socket的規定去編程,寫出的程序自然就是遵循tcp/udp標準的。Python 提供了兩個基本的 socket 模塊。第一個是 Socket,它提供了標準的 BSD Sockets API。第二個是 SocketServer, 它提供了伺服器中心類,可以簡化網絡伺服器的開發。
  • Python 基於 Socket 實現群聊
    來源:博客園-hunyhttps://www.cnblogs.com/huny/p/14051152.html【導語】網際網路時代,怎麼能不懂點網絡編程
  • Python Socket 編程學習筆記
    套接字(socket):套接字是對網絡通訊過程中端點的抽象表示,包含進行網絡通信必須的五種信息:連接使用的協議,本地主機的IP位址,本地進程的協議埠,遠地主機的IP位址,遠地進程的協議埠。通過socket,就能建立server和client之間的連接了。2.
  • Python3 網絡編程|python|伺服器|應用程式|調用|tcp_網易訂閱
    Python 提供了兩個級別訪問的網絡服務。:  低級別的網絡服務支持基本的 Socket,它提供了標準的 BSD Sockets API,可以訪問底層作業系統Socket接口的全部方法。高級別的網絡服務模塊 SocketServer, 它提供了伺服器中心類,可以簡化網絡伺服器的開發。
  • Python網絡編程socket模塊實例解析
    網絡也是IO的一種,在Python中有專門的socket模塊用來處理網絡操作的。
  • 使用Python進行UDP編程
    一定還是不要害羞儘管找技術支持,因為我的是義大利電源,所以主要是通過發郵件,幸好遇到的技術支持人非常的及時,基本第二天就給我回復消息了,當然你也絕不能指望他能給你有更大的幫助,只是最起碼能驗證自己心裡的猜想,我又問他要了一個demo,他給我發了一段python代碼。
  • Linux C網絡編程[Socket]
    現在的跨平臺網絡編程框架很多,如Java的SSH,C/C++的Boost等。  現在的分布式框架很多,如Hadoop等。  我的任務是把一個C/C++程序做成分布式,要求的不配環境,基本屬於純計算的,結果很小。所以選擇了Socket。
  • Linux C語言高級編程之Socket網絡編程!
    Socket網絡編程網絡上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個
  • Java socket編程
    一,網絡編程中兩個主要的問題一個是如何準確的定位網絡上一臺或多臺主機,另一個就是找到主機後如何可靠高效的進行數據傳輸。在TCP/IP協議中IP層主要負責網絡主機的定位,數據傳輸的路由,由IP位址可以唯一地確定Internet上的一臺主機。
  • 網絡編程基礎學習筆記2:socket接口及網絡編程三要素
    對於網絡編程而言,由於其底層語言是通過C語言來實現的,所以建議在學習的時候使用C語言來進行學習!網絡編程中常用的socket接口如下:socket()接口,用於創建socket;bind():用於綁定socket到本地地址和埠,通常由服務端調用(客戶端一般直接由connect直接主動去連結服務端);listen():用於開啟監聽模式,TCP專用;accept():用於伺服器等待客戶端連接,該情況一般在阻塞狀態下產生
  • 讀懂Java中的Socket編程
    如今大多數基於網絡的軟體,如瀏覽器,即時通訊工具甚至是P2P下載都是基於Socket實現的。本文會介紹一下基於TCP/IP的Socket編程,並且如何寫一個客戶端/伺服器程序。在使用流通信之前,我們必須在通信的一對兒socket之間建立連接。其中一個socket作為伺服器進行監聽連接請求。另一個則作為客戶端進行連接請求。一旦兩個socket建立好了連接,他們可以單向或雙向進行數據傳輸。  讀到這裡,我們多少有這樣的疑問,我們進行socket編程使用UDP還是TCP呢。選擇基於何種協議的socket編程取決於你的具體的客戶端-伺服器端程序的應用場景。
  • python socket實戰(一)
    每周一07:22,準時為你充電最近一直在用python編寫socket
  • 基於Socket的java通信編程詳解
    Java最初是作為網絡程式語言出現的,其對網絡提供了高度的支持,使得客戶端和伺服器的溝通變成了現實,而在網絡編程中,使用最多的就是Socket。像大家熟悉的QQ、MSN都使用了Socket相關的技術。下面就讓我們一起揭開Socket的神秘面紗。
  • PHP SOCKET編程
    該函數在讀取完 length 個字節數,或到達 EOF 的時候,或(對於網絡流)當一個包可用時就會停止讀取文件,視乎先碰到哪種情況。 可以看出對於網絡流就必須注意取到的是一個完整的包就停止。2、php擴展模塊帶有的socket功能。
  • 網絡編程基礎之Socket概述
    概念Socket接口是TCP/IP網絡的API,通過此接口,可以開發TCP/IP網絡上的應用程式。Socket接口是一種特殊的I/O,也是一種文件描述符。我們調用類似於打開文件的函數打開Socket,會返回一個Socket描述符。