day26-20180531筆記

筆記:Python3 的網絡編程socketpython

 

1、socket編程

Python 提供了兩個級別訪問的網絡服務。:服務器

  • 低級別的網絡服務支持基本的 Socket,它提供了標準的 BSD Sockets API,能夠訪問底層操做系統Socket接口的所有方法。
  • 高級別的網絡服務模塊 SocketServer, 它提供了服務器中心類,能夠簡化網絡服務器的開發。

什麼是 Socket?

Socket又稱"套接字",應用程序一般經過"套接字"向網絡發出請求或者應答網絡請求,使主機間或者一臺計算機上的進程間能夠通信。網絡

socket()函數

Python 中,咱們用 socket()函數來建立套接字,語法格式以下:socket

socket.socket([family[, type[, proto]]])

參數

  • family: 套接字家族能夠使AF_UNIX或者AF_INET
  • type: 套接字類型能夠根據是面向鏈接的仍是非鏈接分爲SOCK_STREAMSOCK_DGRAM
  • protocol: 通常不填默認爲0.

Socket 對象(內建)方法

函數 描述
服務器端套接字
s.bind() 綁定地址(host,port)到套接字, 在AF_INET下,以元組(host,port)的形式表示地址。
s.listen() 開始TCP監聽。backlog指定在拒絕鏈接以前,操做系統能夠掛起的最大鏈接數量。該值至少爲1,大部分應用程序設爲5就能夠了。
s.accept() 被動接受TCP客戶端鏈接,(阻塞式)等待鏈接的到來
客戶端套接字
s.connect() 主動初始化TCP服務器鏈接,。通常address的格式爲元組(hostname,port),若是鏈接出錯,返回socket.error錯誤。
s.connect_ex() connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常
公共用途的套接字函數
s.recv() 接收TCP數據,數據以字符串形式返回,bufsize指定要接收的最大數據量。flag提供有關消息的其餘信息,一般能夠忽略。
s.send() 發送TCP數據,將string中的數據發送到鏈接的套接字。返回值是要發送的字節數量,該數量可能小於string的字節大小。
s.sendall() 完整發送TCP數據,完整發送TCP數據。將string中的數據發送到鏈接的套接字,但在返回以前會嘗試發送全部數據。成功返回None,失敗則拋出異常。
s.recvfrom() 接收UDP數據,與recv()相似,但返回值是(data,address)。其中data是包含接收數據的字符串,address是發送數據的套接字地址。
s.sendto() 發送UDP數據,將數據發送到套接字,address是形式爲(ipaddr,port)的元組,指定遠程地址。返回值是發送的字節數。
s.close() 關閉套接字
s.getpeername() 返回鏈接套接字的遠程地址。返回值一般是元組(ipaddr,port)。
s.getsockname() 返回套接字本身的地址。一般是一個元組(ipaddr,port)
s.setsockopt(level,optname,value) 設置給定套接字選項的值。
s.getsockopt(level,optname[.buflen]) 返回套接字選項的值。
s.settimeout(timeout) 設置套接字操做的超時期,timeout是一個浮點數,單位是秒。值爲None表示沒有超時期。通常,超時期應該在剛建立套接字時設置,由於它們可能用於鏈接的操做(如connect())
s.gettimeout() 返回當前超時期的值,單位是秒,若是沒有設置超時期,則返回None。
s.fileno() 返回套接字的文件描述符。
s.setblocking(flag) 若是flag爲0,則將套接字設爲非阻塞模式,不然將套接字設爲阻塞模式(默認值)。非阻塞模式下,若是調用recv()沒有發現任何數據,或send()調用沒法當即發送數據,那麼將引發socket.error異常。
s.makefile() 建立一個與該套接字相關連的文件

簡單實例

服務端

咱們使用 socket 模塊的 socket 函數來建立一個 socket 對象。socket 對象能夠經過調用其餘函數來設置一個 socket 服務。函數

如今咱們能夠經過調用 bind(hostname, port) 函數來指定服務的 port(端口)測試

接着,咱們調用 socket 對象的 accept 方法。該方法等待客戶端的鏈接,並返回 connection 對象,表示已鏈接到客戶端。大數據

完整代碼以下:url

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/6/2 08:35
# @Author  : yangyuanqiang
# @File    : server.py


# 導入 socket、sys 模塊
import socket
import sys

# 建立 socket 對象
serversocket = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM)

# 獲取本地主機名
# host = socket.gethostname()
host = ('192.168.3.11')
print(host)

port = 9999

# 綁定端口號
serversocket.bind((host, port))

# 設置最大鏈接數,超事後排隊
serversocket.listen(5)

while 1:
    # 創建客戶端鏈接
    clientsocket, addr = serversocket.accept()

    print("鏈接地址: %s" % str(addr))

    msg = '歡迎訪問測試頁面!' + "\r\n"
    clientsocket.send(msg.encode('utf-8'))
    clientsocket.close()

客戶端

接下來咱們寫一個簡單的客戶端實例鏈接到以上建立的服務。端口號爲 9999。spa

socket.connect(hosname, port ) 方法打開一個 TCP 鏈接到主機爲 hostname 端口爲 port 的服務商。鏈接後咱們就能夠從服務端獲取數據,記住,操做完成後須要關閉鏈接。

完整代碼以下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/6/2 08:36
# @Author  : yangyuanqiang
# @File    : client.py


# 導入 socket、sys 模塊
import socket
import sys

# 建立 socket 對象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 獲取本地主機名
host = socket.gethostname()

# 設置端口號
port = 9999

# 鏈接服務,指定主機和端口
s.connect((host, port))

# 接收小於 1024 字節的數據
msg = s.recv(1024)

s.close()

print (msg.decode('utf-8'))

終端執行 server.py 文件:

$ python3 server.py

第二個終端執行 client.py 文件:

$ python3 client.py

這是咱們再打開第一個終端,就會看到有如下信息輸出:

鏈接地址: ('192.168.3.11', 50067)

Python Internet 模塊

如下列出了 Python 網絡編程的一些重要模塊:

協議 功能用處 端口號 Python 模塊
HTTP 網頁訪問 80 httplib, urllib, xmlrpclib
NNTP 閱讀和張貼新聞文章,俗稱爲"帖子" 119 nntplib
FTP 文件傳輸 20 ftplib, urllib
SMTP 發送郵件 25 smtplib
POP3 接收郵件 110 poplib
IMAP4 獲取郵件 143 imaplib
Telnet 命令行 23 telnetlib
Gopher 信息查找 70 gopherlib, urllib

實例:

服務端:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/5/31 21:30
# @Author  : yangyuanqiang
# @File    : server.py

import socket

import time

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = ('192.168.3.11', 6666)
s.bind(address)
s.listen(10)
print("start server!")
while 1:
    try:
        conn, addr = s.accept()
        if conn:
            print("recv client from {0}".format(addr))
            while 1:
                data = conn.recv(2048)
                print("recv data: {0}".format(data.decode('utf-8')))
                conn.sendall(data.decode('utf-8').upper().encode('utf-8'))
        else:
            time.sleep(5)
    except Exception as e:
        conn.close()

客戶端:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/5/31 21:30
# @Author  : yangyuanqiang
# @File    : client.py



import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = ('192.168.3.11', 6666)
s.connect(address)
flage = 1
print("start client!")
while flage:
    word = input("word: ")
    if word == "exit":
        flage = 0
    s.sendall(word.encode('utf-8'))
    data = s.recv(2048)
    print("RECV: {0}".format(data.decode('utf-8')))

s.close()

客戶端輸出的結果:

start client!
word: hi
RECV: HI
word: hello
RECV: HELLO
word: 

服務端接收的結果:

start server!
recv client from ('192.168.3.11', 50199)
recv data: hi
recv data: hello

注意:以上實例,只能打開一個客戶端終端向服務端發送消息請求,不能同時打開多個客戶端,一發一收。

相關文章
相關標籤/搜索