socket網絡編程

c/s架構:客戶端/服務器架構python

C/S架構與socket的關係:shell

咱們學習socket就是爲了完成C/S架構的開發編程

 

爲什麼學習socket必定要先學習互聯網協議:設計模式

1.首先:本節課程的目標就是教會你如何基於socket編程,來開發一款本身的C/S架構軟件緩存

2.其次:C/S架構的軟件(軟件屬於應用層)是基於網絡進行通訊的服務器

3.而後:網絡的核心即一堆協議,協議即標準,你想開發一款基於網絡通訊的軟件,就必須遵循這些標準。網絡

4.最後:就讓咱們從這些標準開始研究,開啓咱們的socket編程之旅架構

 

socket層ssh

 socket是什麼

Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。socket

因此,咱們無需深刻理解tcp/udp協議,socket已經爲咱們封裝好了,咱們只須要遵循socket的規定去編程,寫出的程序天然就是遵循tcp/udp標準的。

 套接字發展史及分類

套接字起源於 20 世紀 70 年代加利福尼亞大學伯克利分校版本的 Unix,即人們所說的 BSD Unix。 所以,有時人們也把套接字稱爲「伯克利套接字」或「BSD 套接字」。一開始,套接字被設計用在同 一臺主機上多個應用程序之間的通信。這也被稱進程間通信,或 IPC。套接字有兩種(或者稱爲有兩個種族),分別是基於文件型的和基於網絡型的。 

基於文件類型的套接字家族

套接字家族的名字:AF_UNIX

unix一切皆文件,基於文件的套接字調用的就是底層的文件系統來取數據,兩個套接字進程運行在同一機器,能夠經過訪問同一個文件系統間接完成通訊

基於網絡類型的套接字家族

套接字家族的名字:AF_INET

(還有AF_INET6被用於ipv6,還有一些其餘的地址家族,不過,他們要麼是隻用於某個平臺,要麼就是已經被廢棄,或者是不多被使用,或者是根本沒有實現,全部地址家族中,AF_INET是使用最普遍的一個,python支持不少種地址家族,可是因爲咱們只關心網絡編程,因此大部分時候我麼只使用AF_INET)

 

套接字工做流程

服務端套接字函數
s.bind() 綁定(主機,端口號)到套接字
s.listen() 開始TCP監聽
s.accept() 被動接受TCP客戶的鏈接,(阻塞式)等待鏈接的到來

客戶端套接字函數
s.connect() 主動初始化TCP服務器鏈接
s.connect_ex() connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常

公共用途的套接字函數
s.recv() 接收TCP數據
s.send() 發送TCP數據(send在待發送數據量大於己端緩存區剩餘空間時,數據丟失,不會發完)
s.sendall() 發送完整的TCP數據(本質就是循環調用send,sendall在待發送數據量大於己端緩存區剩餘空間時,數據不丟失,循環調用send直到發完)
s.recvfrom() 接收UDP數據
s.sendto() 發送UDP數據
s.getpeername() 鏈接到當前套接字的遠端的地址
s.getsockname() 當前套接字的地址
s.getsockopt() 返回指定套接字的參數
s.setsockopt() 設置指定套接字的參數
s.close() 關閉套接字

面向鎖的套接字方法
s.setblocking() 設置套接字的阻塞與非阻塞模式
s.settimeout() 設置阻塞套接字操做的超時時間
s.gettimeout() 獲得阻塞套接字操做的超時時間

面向文件的套接字的函數
s.fileno() 套接字的文件描述符
s.makefile() 建立一個與該套接字相關的文件

 

import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('192.168.20.105',8080))
phone.listen(5)
while 1:
    conn,addr=phone.accept()
    print('線路是%s' % conn)
    print('地址是',addr)
    while 1:
        try:
            cmd = conn.recv(1024)
            conn.send(cmd.upper())
        except Exception:
            break
    conn.close()
phone.close()
tcp服務端
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('192.168.20.105',8080))
while 1:
    sends = input('>>:')
    if not sends:continue
    phone.send(sends.encode('utf-8'))
    mess = phone.recv(1024)
    print(mess)

phone.close()
tcp客戶端
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
from socket import *
import subprocess

ip_port=('127.0.0.1',8080)
BUFSIZE=1024

tcp_socket_server=socket(AF_INET,SOCK_STREAM)
tcp_socket_server.bind(ip_port)
tcp_socket_server.listen(5)

while True:
    conn,addr=tcp_socket_server.accept()
    print('客戶端',addr)

    while True:
        cmd=conn.recv(BUFSIZE)
        if len(cmd) == 0:break

        res=subprocess.Popen(cmd.decode('utf-8'),shell=True,
                         stdout=subprocess.PIPE,
                         stdin=subprocess.PIPE,
                         stderr=subprocess.PIPE)

        stderr=act_res.stderr.read()
        stdout=act_res.stdout.read()
        conn.send(stderr)
        conn.send(stdout)
模擬遠程ssh
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
import socket
BUFSIZE=1024
ip_port=('127.0.0.1',8080)

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(ip_port)

while True:
    msg=input('>>: ').strip()
    if len(msg) == 0:continue
    if msg == 'quit':break

    s.send(msg.encode('utf-8'))
    act_res=s.recv(BUFSIZE)

    print(act_res.decode('utf-8'),end='')
ssh客戶端

 

import socket
import hashlib
import subprocess
import os

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)   #重用地址
phone.bind(('192.168.20.105',8081))
phone.listen(5)
while 1:
    conn,addr=phone.accept()
    print('線路是%s' % conn)
    print('地址是',addr)
    tag = True
    while 1:
        while tag:
            user = conn.recv(1024).decode('utf-8')
            pwd = conn.recv(1024).decode('utf-8')
            md5_obj = hashlib.md5(user.encode('utf-8'))
            s = pwd+user
            print(s)
            md5_obj.update(s.encode('utf-8'))
            pwd = md5_obj.hexdigest()
            print(pwd)
            if user == 'egon'and pwd=='82bdb4164c14585f32e70ec0a37b3569':
                conn.send('right'.encode('utf-8'))
                tag = False
                break
            else:
                conn.send('用戶名或密碼錯誤,請從新輸入!'.encode('utf-8'))
        try:
            cmd = conn.recv(1024)
            res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            mes = res.stdout.read()
            mesr = res.stderr.read()
            conn.send(str(len(mes+mesr)).encode('utf-8'))
            conn.send(mes+mesr)
        except Exception:
            break
    conn.close()
phone.close()
增長登錄認證和解決粘包
import socket
import time

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('192.168.20.105',8081))
tag = True
while 1:
    while tag:
        user = input('username:')
        pwd = input('password:')
        phone.send(user.encode('utf-8'))
        phone.send(pwd.encode('utf-8'))
        time.sleep(1)
        mes = phone.recv(1024).decode('utf-8')
        print(mes)
        if mes =='right':
            tag = False
            break
    cmd = input('>>:')
    if not cmd:continue
    phone.send(cmd.encode('utf-8'))
    lens = phone.recv(1024).decode('utf-8')
    mes = phone.recv(1024)
    while 1:
        if int(lens)>len(mes):
            mes+=phone.recv(1024)
        else:
            break
    print(mes.decode('gbk'))

phone.close()
客戶端
相關文章
相關標籤/搜索