python socket編程

 

什麼是 Socket?


Socket又稱"套接字",應用程序一般經過"套接字"向網絡發出請求或者應答網絡請求,使主機間或者一臺計算機上的進程間能夠通信。
TCP可靠性的實現:
(1)校驗碼
(2)接收方反饋
(3)信息包附帶序號
UDP:(1)快 不須要花費時間創建和關閉鏈接
(2)快 偶爾丟失一兩個消息包無所謂,可是TCP會嚴格檢查
(3)快 UDP的限制是一個信息包不超過64KB的數據
TCP和UDP區別就是UDP不創建鏈接,只保證數據的完整性,數據傳輸快,可是不保證數據是否真的被收到,也不保證數據是夠只接收一次,也不保證次序。python

服務端是用來給一個或者多個客戶端提供服務的,當客戶端發起請求,開始等待服務端的返回結果,服務端接受完請求之後,根據本身的邏輯進行處理請求,並返回給客戶端,客戶端接收到返回結果之後,關閉和服務端的鏈接。mysql

最經常使用個客戶端和服務端有兩種模式C/S(mysql)模式和B/S模式(網站)sql

 

socket()函數


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

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

參數

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

 

TCP

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

綁定地址

bind(address)
address = (‘0.0.0.0’, 8009)
s.bind(address) 或者s.bind((‘0.0.0.0’, 8009))
address 必須是一個元組,容易錯誤,address = (host,port)
host:服務端ip,字符串類型, 若是爲0.0.0.0 表明本機的任意一個ip
port:服務端提供的端口, 整型, 0-1024爲系統保留ssh

監聽消息

s.listen(badklog)
backlog表明能夠同時接受多少個socket鏈接socket

接受鏈接

conn, addr = s.accept()
接受鏈接並返回元組(conn, addr), 其中conn是新的套接字對象,每個新的鏈接就建立一個新的對象。能夠用來接受和發送數據,addr是客戶端的地址。包含host和port函數

發送數據

s.send(string) 發送字符串到鏈接的套接字,可能未將指定內容所有發送
s.sendall(string) 內部遞歸調用send,將全部內容發送出去,建議使用。網站

接收數據

data = s.recv(bufsize)
接收套接字數據,數據以字符串形式返回,bufsize指定最多接收的數據量,能夠使用1024, 2048
若是不知道接收的數量有多少,可能幾個字節,可能幾M,通常經過循環接收ui

 

UDP

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(string)
data, address = s.recvfrom(bufsize)

客戶端

客戶端首先也要建立socket套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
客戶端鏈接服務端函數:
s.connect(address) 鏈接到address的套接字
result = connect_ex(address) 成功返回0,失敗返回錯誤碼(推薦使用)

通用

s.close() 關閉socket套接字
s.getsocketname() 獲取套接字的名字
s.settimeout(timeout) 設置套接字超時時間,timeout爲float類型,單位爲秒。
s.gettimeout() 得到套接字超時時間

s.setblocking(flag)
flage爲bool值
setblocking(True) is equivalent to settimeout(None); 至關於不設置超時時間,一直阻塞在那裏
setblocking(False) is equivalent to settimeout(0.0). 至關於設置超時時間爲0, 若是設置False,那麼accept和recv時一旦無數據,則報錯。

s.fileno()
返回套接字的文件描述符(一個小整數)。這對於select.select()是有用的。

 

簡單例子

客戶端向服務端發送一個消息。

服務端

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time  : 2018-6-1 17:52
# @Author: yangjian
# @File  : Client.py


'''
python3 socket收發消息都是隻能使用bytes類型,而python2.7則能夠使用str類型
'''

'''
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
參數一:地址簇
  socket.AF_INET IPv4(默認)
  socket.AF_INET6 IPv6
  socket.AF_UNIX 只可以用於單一的Unix系統進程間通訊
參數二:類型
  socket.SOCK_STREAM  流式socket , for TCP (默認)
  socket.SOCK_DGRAM   數據報式socket , for UDP
    socket.SOCK_RAW 原始套接字,普通的套接字沒法處理ICMP、IGMP等網絡報文,而SOCK_RAW能夠;其次,SOCK_RAW也能夠處理
                    特殊的IPv4報文;此外,利用原始套接字,能夠經過IP_HDRINCL套接字選項由用戶構造IP頭。
  socket.SOCK_RDM 是一種可靠的UDP形式,即保證交付數據報但不保證順序。SOCK_RAM用來提供對原始協議的低級訪問,在須要
                    執行某些特殊操做時使用,如發送ICMP報文。SOCK_RAM一般僅限於高級用戶或管理員運行的程序使用。
  socket.SOCK_SEQPACKET 可靠的連續數據包服務
參數三:協議
 (默認)與特定的地址家族相關的協議,若是是 0 ,則系統就會根據地址格式和套接類別,自動選擇一個合適的協議
'''

import socket

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


#綁定
ip_port = ('127.0.0.1',8087)  #定義ip、端口號
s.bind(ip_port)  #socket對象綁定ip、端口號(ip、端口號必定是元組形式)

s.getsockname()  #服務端使用,返回服務端自身的套接字地址(ip、端口號)

#監聽,並設置最大掛起鏈接數
s.listen(5)  #監聽,除了正在鏈接的客戶端,最多還能能掛起5個鏈接,超過以後就拒絕鏈接


#獲取客戶端鏈接
conn, addr = s.accept()   #獲取客戶端的scoket對象conn和客戶端的地址address(ip、端口號)


#收發消息
recv_data = conn.recv(1024)   #socket獲取的客戶端對象(conn)用來接收消息
print(str(recv_data,encoding='utf-8'))
send_data = '你好'
conn.send(bytes(send_data,encoding='utf-8'))   #socket獲取的客戶端對象(conn)用來發送消息-----python3只能發送字節類型(bytes),python2.7能夠直接發送字符串

#關閉客戶端對象
conn.close()

 

客戶端

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time  : 2018-6-1 17:51
# @Author: yangjian
# @File  : Server.py

'''
python3 socket收發消息都是隻能使用bytes類型,而python2.7則能夠使用str類型
'''

import socket

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

s.settimeout(5)   #設置超時時間
#s.getpeername()  #客戶端使用,返回服務端的套接字地址(ip、端口號)

#鏈接服務端
#ip_port = ('127.0.0.1',9999)  #定義ip、端口號
s.connect(('127.0.0.1',8087))  #socket對象鏈接服務端。(ip、端口號必定是元組形式) ----鏈接失敗會報錯
#s.connect_ex(ip_port)   #功能同上,不過若是鏈接失敗會返回一個錯誤編碼(不報錯)


#發消息
send_data = '你好'
s.send(bytes(send_data,encoding='utf-8'))    #發送消息,成功返回發送的字節數-----python3只能發送字節類型(bytes),python2.7能夠直接發送字符串
#s.sendall(bytes(send_data,encoding='utf-8'))   #發送全部數據,成功返回None,失敗報錯

#收消息
recv_data = s.recv(1024)


#關閉
s.close()

 

ssh交互

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time  : 2018-6-1 18:15
# @Author: yangjian
# @File  : ssh_test.py

import paramiko


client = paramiko.SSHClient()
# 容許連接不在know_host文件中的主機
client.set_missing_host_key_policy(paramiko.AutoAddPolicy)

client.connect('100.106.106.220', 22, username='root', password='123456', timeout=5)
while 1:
    cmd = input('[root@localhost ~]#')
    stdin, stdout, stderr = client.exec_command(cmd)
    for std in stdout.readlines():
        print(std)
client.close()

結果:
D:\pycharmproject\venv\Scripts\python.exe D:/pycharmproject/0531/ssh_test.py
[root@localhost ~]#ls -ll
total 8
-rw-r--r-- 1 root root 1361 May 31 10:11 yangjian.his
-rw-r--r-- 1 root root  924 May 31 10:11 yangjian.time
相關文章
相關標籤/搜索