亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Python > 正文

詳解Python Socket網絡編程

2020-01-04 17:52:23
字體:
來源:轉載
供稿:網友
這篇文章主要為大家介紹了Python Socket網絡編程,主要介紹使用 Python 進行 TCP Socket網絡編程
 

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

本文主要介紹使用Python 進行TCP Socket 網絡編程,假設你已經具有初步的網絡知識及Python 基本語法知識。

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

一、客戶端編程
創建socket

首先要創建 socket,用 Python 中 socket 模塊的函數 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'

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

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

錯誤處理

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

#handling errors in python socket programs import socket  #for socketsimport 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'

那么到目前為止已成功創建了 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:  #could not resolve  print 'Hostname could not be resolved. Exiting'  sys.exit()   print 'Ip address of ' + host + ' is ' + remote_ip

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

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

運行該程序:

$ python client.pySocket createdIp of remote host www.google.com is 173.194.38.145Socket Connected to www.google.com on ip 173.194.38.145

發送數據

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

#Send some data to remote servermessage = "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'

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

接收數據

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

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

一起運行的結果如下:

 

Socket createdIp of remote host www.google.com is 173.194.38.145Socket Connected to www.google.com on ip 173.194.38.145Message send successfullyHTTP/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><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 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 = ''  # Symbolic name meaning all available interfacesPORT = 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'

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

監聽連接

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

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

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

接收連接

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

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

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

$ python server.pySocket createdSocket bind completeSocket now listening

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

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

這時服務端輸出會顯示:

$ python server.pySocket createdSocket bind completeSocket now listeningConnected with 127.0.0.1:59954

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

import socketimport sys HOST = ''  # Symbolic name meaning all available interfacesPORT = 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 callconn, addr = s.accept() print 'Connected with ' + addr[0] + ':' + str(addr[1]) #now keep talking with the clientdata = conn.recv(1024)conn.sendall(data) conn.close()s.close()

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

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

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

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

保持服務

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

import socketimport sys HOST = ''  # Symbolic name meaning all available interfacesPORT = 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 clientwhile 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()

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

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

處理連接

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

import socketimport sysfrom thread import * HOST = ''  # Symbolic name meaning all available interfacesPORT = 8888 # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)print 'Socket created' #Bind socket to local host and porttry:  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 sockets.listen(10)print 'Socket now listening' #Function for handling connections. This will be used to create threadsdef 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 clientwhile 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()

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

telnet 終端下可能輸出如下:

$ telnet localhost 8888Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Welcome to the server. Type something and hit enterhiOK...hiasdOK...asdcvOK...cv

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

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

$ python server.pySocket createdSocket bind completeSocket now listeningConnected with 127.0.0.1:60730Connected with 127.0.0.1:60731

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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情乱人伦一区| 国产不卡视频在线| 欧美天天综合色影久久精品| 精品国产乱码久久久久久天美| 久久国产精品久久久久| 亚洲欧美激情一区| 一区二区三区亚洲| 欧美亚洲第一区| 亚洲精品在线视频| 欧美噜噜久久久xxx| 亚洲精品美女在线| 久久久国产成人精品| 91精品国产综合久久久久久久久| 国产亚洲欧美日韩精品| 成人免费淫片视频软件| 精品国产一区二区三区四区在线观看| 亚洲第一av网站| 在线电影欧美日韩一区二区私密| 久久精品2019中文字幕| 美日韩在线视频| 欧美极品美女电影一区| 日韩欧美在线字幕| 久久九九国产精品怡红院| 国产精品专区h在线观看| 色偷偷88888欧美精品久久久| 91久久国产综合久久91精品网站| 日韩在线国产精品| 国产欧美精品一区二区三区介绍| 精品女厕一区二区三区| 国产午夜精品全部视频在线播放| 欧美乱大交做爰xxxⅹ性3| 欧美激情a∨在线视频播放| 成人写真视频福利网| 日韩精品在线观看一区二区| 成人妇女免费播放久久久| 一本久久综合亚洲鲁鲁| 国产免费观看久久黄| 国产婷婷97碰碰久久人人蜜臀| 亚洲亚裔videos黑人hd| 综合欧美国产视频二区| 亚洲视频第一页| 国产乱人伦真实精品视频| 国产精品无av码在线观看| 成人黄色在线观看| 亚洲国产精品va在看黑人| 国产精品精品视频| 午夜精品蜜臀一区二区三区免费| 欧美体内谢she精2性欧美| 茄子视频成人在线| 中文字幕精品一区二区精品| 九九精品视频在线| 97精品久久久中文字幕免费| 日韩福利视频在线观看| 成人在线一区二区| 日韩在线一区二区三区免费视频| 久久人人爽人人爽人人片亚洲| 97成人精品视频在线观看| 久久九九国产精品怡红院| 亚洲一区中文字幕| 国产在线视频91| 日韩激情av在线播放| 欧美激情图片区| 欧美高清性猛交| 亚洲精品第一页| 日本精品一区二区三区在线播放视频| 91精品免费久久久久久久久| 久久久久久久久久久网站| 国产精品69精品一区二区三区| 国产精品久久久久久av下载红粉| 国产亚洲成av人片在线观看桃| 在线视频欧美性高潮| 国产精品69精品一区二区三区| 777午夜精品福利在线观看| 欧美性生交大片免网| 另类天堂视频在线观看| 欧美性猛交xxxxx免费看| 91高清在线免费观看| 在线播放日韩精品| 久久中文字幕在线| 亚洲free性xxxx护士hd| 国产美女精品视频| 亚洲午夜色婷婷在线| 伊人久久久久久久久久| 国产亚洲激情在线| 国产精品美女网站| 91中文字幕在线观看| 亚洲的天堂在线中文字幕| 亚洲品质视频自拍网| 国产精品专区第二| 欧美午夜影院在线视频| 精品久久久中文| 久久久久久美女| 久久久精品一区二区三区| 亚洲精品一区二区在线| 日韩精品免费电影| 国产一区二区在线播放| 欧美另类xxx| 欧美一级电影久久| 国产91在线高潮白浆在线观看| 亚洲人成五月天| 日韩电影免费在线观看| 欧美wwwwww| 久久久久久久久久久91| 91久久嫩草影院一区二区| 午夜剧场成人观在线视频免费观看| 国产日产亚洲精品| 久久久在线免费观看| 黄色精品一区二区| 久久精品国产电影| 91中文在线观看| 91最新在线免费观看| 中文字幕亚洲天堂| 国产丝袜一区二区三区免费视频| 日本久久亚洲电影| 国产精品丝袜一区二区三区| 亚洲一区二区三区视频| 久久精品国产一区二区电影| 亚洲一区二区三区乱码aⅴ蜜桃女| 91超碰caoporn97人人| 亚洲美女性视频| 成人激情黄色网| 亚洲jizzjizz日本少妇| 在线性视频日韩欧美| 亚洲va欧美va国产综合剧情| 日本精品性网站在线观看| 欧美老女人在线视频| 国产精品av在线播放| 91影视免费在线观看| 91精品国产网站| 久久久爽爽爽美女图片| 91人成网站www| 欧美成人网在线| 亚洲新声在线观看| 久久久精品在线| 日韩电视剧免费观看网站| 国产精品美女999| 欧美视频裸体精品| 高清一区二区三区日本久| 91欧美精品成人综合在线观看| 国产精品极品尤物在线观看| 久久久久久美女| 日韩精品视频免费| 欧美一级电影久久| 久久亚洲精品中文字幕冲田杏梨| 欧美日韩亚洲国产一区| 国产精品免费久久久| 欧美黄网免费在线观看| 日韩成人在线网站| 九九精品在线播放| 欧美午夜xxx| 日本电影亚洲天堂| 国产精品永久免费观看| 亚洲成av人影院在线观看| 国产精品久久二区| 日韩有码在线视频| 亚洲性69xxxbbb| 日韩欧美国产免费播放| 影音先锋欧美精品| 亚洲视频在线观看网站| 亚洲午夜久久久久久久| 91久久久久久久一区二区| 亚洲欧洲国产伦综合| 日韩在线观看av| 亚洲精品日韩丝袜精品|