最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Python Socket網(wǎng)絡(luò)編程

 更新時間:2016年01月05日 11:45:21   投稿:lijiao  
這篇文章主要為大家介紹了Python Socket網(wǎng)絡(luò)編程,主要介紹使用 Python 進行 TCP Socket網(wǎng)絡(luò)編程

Socket 是進程間通信的一種方式,它與其他進程間通信的一個主要不同是:它能實現(xiàn)不同主機間的進程間通信,我們網(wǎng)絡(luò)上各種各樣的服務(wù)大多都是基于 Socket 來完成通信的,例如我們每天瀏覽網(wǎng)頁、QQ 聊天、收發(fā) email 等等。要解決網(wǎng)絡(luò)上兩臺主機之間的進程通信問題,首先要唯一標識該進程,在 TCP/IP 網(wǎng)絡(luò)協(xié)議中,就是通過 (IP地址,協(xié)議,端口號) 三元組來標識進程的,解決了進程標識問題,就有了通信的基礎(chǔ)了。

本文主要介紹使用Python 進行TCP Socket 網(wǎng)絡(luò)編程,假設(shè)你已經(jīng)具有初步的網(wǎng)絡(luò)知識及Python 基本語法知識。

TCP 是一種面向連接的傳輸層協(xié)議,TCP Socket 是基于一種 Client-Server 的編程模型,服務(wù)端監(jiān)聽客戶端的連接請求,一旦建立連接即可以進行傳輸數(shù)據(jù)。那么對 TCP Socket 編程的介紹也分為客戶端和服務(wù)端:

一、客戶端編程
創(chuàng)建socket

首先要創(chuàng)建 socket,用 Python 中 socket 模塊的函數(shù) socket 就可以完成:

#Socket client example in python
 
import socket  #for sockets
 
#create an AF_INET, STREAM socket (TCP)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
print 'Socket Created'

函數(shù)socket.socket 創(chuàng)建一個 socket,返回該 socket 的描述符,將在后面相關(guān)函數(shù)中使用。該函數(shù)帶有兩個參數(shù):

Address Family:可以選擇 AF_INET(用于 Internet 進程間通信) 或者 AF_UNIX(用于同一臺機器進程間通信)
Type:套接字類型,可以是 SOCKET_STREAM(流式套接字,主要用于 TCP 協(xié)議)或者SOCKET_DGRAM(數(shù)據(jù)報套接字,主要用于 UDP 協(xié)議)
注:由于本文主要概述一下 Python Socket 編程的過程,因此不會對相關(guān)函數(shù)參數(shù)、返回值進行詳細介紹,需要了解的可以查看相關(guān)手冊

錯誤處理

如果創(chuàng)建 socket 函數(shù)失敗,會拋出一個 socket.error 的異常,需要捕獲:

#handling errors in python socket programs
 
import socket  #for sockets
import sys #for exit
 
try:
  #create an AF_INET, STREAM socket (TCP)
  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'

那么到目前為止已成功創(chuàng)建了 socket,接下來我們將用這個 socket 來連接某個服務(wù)器,就連 www.google.com 吧。

連接服務(wù)器

本文開始也提到了,socket 使用 (IP地址,協(xié)議,端口號) 來標識一個進程,那么我們要想和服務(wù)器進行通信,就需要知道它的 IP地址以及端口號。

獲得遠程主機的 IP 地址

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

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

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

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

運行該程序:

$ python client.py
Socket created
Ip of remote host www.google.com is 173.194.38.145
Socket Connected to www.google.com on ip 173.194.38.145

發(fā)送數(shù)據(jù)

上面說明連接到 www.google.com 已經(jīng)成功了,接下面我們可以向服務(wù)器發(fā)送一些數(shù)據(jù),例如發(fā)送字符串GET / HTTP/1.1\r\n\r\n,這是一個 HTTP 請求網(wǎng)頁內(nèi)容的命令。

#Send some data to remote server
message = "GET / HTTP/1.1\r\n\r\n"
 
try :
  #Set the whole string
  s.sendall(message)
except socket.error:
  #Send failed
  print 'Send failed'
  sys.exit()
 
print 'Message send successfully'

發(fā)送完數(shù)據(jù)之后,客戶端還需要接受服務(wù)器的響應(yīng)。

接收數(shù)據(jù)

函數(shù) recv 可以用來接收 socket 的數(shù)據(jù):

#Now receive data
reply = s.recv(4096)
 
print reply

一起運行的結(jié)果如下:

Socket created
Ip of remote host www.google.com is 173.194.38.145
Socket Connected to www.google.com on ip 173.194.38.145
Message send successfully
HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.com.sg/?gfe_rd=cr&ei=PlqJVLCREovW8gfF0oG4CQ
Content-Length: 262
Date: Thu, 11 Dec 2014 08:47:58 GMT
Server: GFE/2.0
Alternate-Protocol: 80:quic,p=0.02

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A >here</A>.
</BODY></HTML>

關(guān)閉 socket

當我們不想再次請求服務(wù)器數(shù)據(jù)時,可以將該 socket 關(guān)閉,結(jié)束這次通信:

s.close()
小結(jié)

上面我們學到了如何:

  • 創(chuàng)建 socket
  • 連接到遠程服務(wù)器
  • 發(fā)送數(shù)據(jù)
  • 接收數(shù)據(jù)
  • 關(guān)閉 socket

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

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

那么上面介紹了客戶端的編程,現(xiàn)在輪到服務(wù)器端如果使用 socket 了。

二、服務(wù)器端編程
服務(wù)器端主要做以下工作:

  • 打開 socket
  • 綁定到特定的地址以及端口上
  • 監(jiān)聽連接
  • 建立連接
  • 接收/發(fā)送數(shù)據(jù)

上面已經(jīng)介紹了如何創(chuàng)建 socket 了,下面一步是綁定。

綁定socket

函數(shù) bind 可以用來將 socket 綁定到特定的地址和端口上,它需要一個 sockaddr_in 結(jié)構(gòu)作為參數(shù):

import socket
import sys
 
HOST = ''  # Symbolic name meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port
 
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'

綁定完成之后,接下來就是監(jiān)聽連接了。

監(jiān)聽連接

函數(shù) listen 可以將 socket 置于監(jiān)聽模式:

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

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

接收連接

當有客戶端向服務(wù)器發(fā)送連接請求時,服務(wù)器會接收連接:

#wait to accept a connection - blocking call
conn, addr = s.accept()
 
#display client information
print 'Connected with ' + addr[0] + ':' + str(addr[1])

運行該程序的,輸出結(jié)果如下:

$ python server.py
Socket created
Socket bind complete
Socket now listening

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

$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

這時服務(wù)端輸出會顯示:

$ python server.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:59954

我們觀察到客戶端已經(jīng)連接上服務(wù)器了。在建立連接之后,我們可以用來與客戶端進行通信。下面例子演示的是,服務(wù)器建立連接之后,接收客戶端發(fā)送來的數(shù)據(jù),并立即將數(shù)據(jù)發(fā)送回去,下面是完整的服務(wù)端程序:

import socket
import sys
 
HOST = ''  # Symbolic name meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port
 
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'
 
#wait to accept a connection - blocking call
conn, addr = s.accept()
 
print 'Connected with ' + addr[0] + ':' + str(addr[1])
 
#now keep talking with the client
data = conn.recv(1024)
conn.sendall(data)
 
conn.close()
s.close()

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

$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
happy
happy
Connection closed by foreign host.

客戶端(telnet)接收了服務(wù)器的響應(yīng)。

我們在完成一次響應(yīng)之后服務(wù)器立即斷開了連接,而像www.google.com 這樣的服務(wù)器總是一直等待接收連接的。我們需要將上面的服務(wù)器程序改造成一直運行,最簡單的辦法是將accept 放到一個循環(huán)中,那么就可以一直接收連接了。

保持服務(wù)

我們可以將代碼改成這樣讓服務(wù)器一直工作:

import socket
import sys
 
HOST = ''  # Symbolic name meaning all available interfaces
PORT = 5000 # Arbitrary non-privileged port
 
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'
 
#now keep talking with the client
while 1:
  #wait to accept a connection - blocking call
  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()

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

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

處理連接

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

import socket
import sys
from thread import *
 
HOST = ''  # Symbolic name meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
 
#Bind socket to local host and port
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'
 
#Start listening on socket
s.listen(10)
print 'Socket now listening'
 
#Function for handling connections. This will be used to create threads
def clientthread(conn):
  #Sending message to connected client
  conn.send('Welcome to the server. Type something and hit enter\n') #send only takes string
   
  #infinite loop so that function do not terminate and thread do not end.
  while True:
     
    #Receiving from client
    data = conn.recv(1024)
    reply = 'OK...' + data
    if not data: 
      break
   
    conn.sendall(reply)
   
  #came out of loop
  conn.close()
 
#now keep talking with the client
while 1:
  #wait to accept a connection - blocking call
  conn, addr = s.accept()
  print 'Connected with ' + addr[0] + ':' + str(addr[1])
   
  #start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
  start_new_thread(clientthread ,(conn,))
 
s.close()

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

telnet 終端下可能輸出如下:

$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome to the server. Type something and hit enter
hi
OK...hi
asd
OK...asd
cv
OK...cv

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

服務(wù)器終端的輸出可能是這樣的:

$ python server.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:60730
Connected with 127.0.0.1:60731

到目前為止,我們學習了Python 下基本的socket 編程,之后還有相關(guān)文章向大家介紹,不要走開。

相關(guān)文章

  • Pandas的Apply函數(shù)具體使用

    Pandas的Apply函數(shù)具體使用

    這篇文章主要介紹了Pandas的Apply函數(shù)具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • python?針對在子文件夾中的md文檔實現(xiàn)批量md轉(zhuǎn)word

    python?針對在子文件夾中的md文檔實現(xiàn)批量md轉(zhuǎn)word

    這篇文章主要介紹了python?針對在子文件夾中的md文檔實現(xiàn)批量md轉(zhuǎn)word,但是自己保存的md文檔在不同的文件夾,而大部分只能實現(xiàn)同一文件夾內(nèi)的轉(zhuǎn)換,得出下列總結(jié),需要的朋友可以參考一下
    2022-04-04
  • 在Django的form中使用CSS進行設(shè)計的方法

    在Django的form中使用CSS進行設(shè)計的方法

    這篇文章主要介紹了在Django的form中使用CSS進行設(shè)計的方法,Django是Python重多人氣開發(fā)框架中最為著名的一個,需要的朋友可以參考下
    2015-07-07
  • python Django框架快速入門教程(后臺管理)

    python Django框架快速入門教程(后臺管理)

    Django 是一個開放源代碼的 Web 應(yīng)用框架,由 Python 寫成,今天通過本文給大家介紹python Django框架快速入門教程,適用后臺管理,感興趣的朋友跟隨小編一起看看吧
    2021-07-07
  • 詳解Python可視化神器Yellowbrick使用

    詳解Python可視化神器Yellowbrick使用

    Yellowbrick是由一套被稱為"Visualizers"組成的可視化診斷工具組成的套餐,其由Scikit-Learn API延伸而來,對模型選擇過程其指導作用。這篇文章主要介紹了Python可視化神器Yellowbrick使用,需要的朋友可以參考下
    2019-11-11
  • 詳解Pycharm第三方庫的安裝及使用方法

    詳解Pycharm第三方庫的安裝及使用方法

    這篇文章主要介紹了詳解Pycharm第三方庫的安裝及使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • pytorch GPU和CPU模型相互加載方式

    pytorch GPU和CPU模型相互加載方式

    在PyTorch中,保存和加載模型有兩種主要方式:直接保存整個模型結(jié)構(gòu)加權(quán)重,或者只保存模型的參數(shù),直接保存整個模型的方法簡單,但不夠靈活,且可能存在模型結(jié)構(gòu)不一致的風險,推薦的做法是只保存模型參數(shù),這種方法需要在加載前定義與原模型結(jié)構(gòu)相同的模型
    2024-09-09
  • Python牛刀小試密碼爆破

    Python牛刀小試密碼爆破

    用Python與vbs分別實現(xiàn)的爆破bbs論壇賬號的代碼,學習python或vbs的朋友可以參考下。
    2011-02-02
  • Python批量圖片去水印的方法

    Python批量圖片去水印的方法

    &#8203;平常工作中,有時為了采用網(wǎng)絡(luò)的一些素材,但這些素材往往被打了水印,如果我們不懂PS就無法去掉水印,或者無法批量去掉水印。本文就介紹了Python批量圖片去水印的方法,感興趣的可以了解一下
    2021-05-05
  • 簡單示例入門了解WxPython教程

    簡單示例入門了解WxPython教程

    這篇文章主要通過演示簡單示例帶大家入門了解WxPython,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11

最新評論

漠河县| 即墨市| 招远市| 察隅县| 南投县| 荆州市| 平利县| 兴山县| 通道| 孝感市| 林口县| 天峨县| 怀来县| 寿光市| 西华县| 石阡县| 曲水县| 马鞍山市| 扶风县| 绥江县| 乌海市| 周口市| 临邑县| 宿松县| 札达县| 和顺县| 伊吾县| 九龙坡区| 甘洛县| 冷水江市| 蓬安县| 波密县| 尤溪县| 如东县| 炉霍县| 郴州市| 花莲市| 乌拉特前旗| 桐乡市| 嘉义县| 光泽县|