快速上手python socket編程

之前在編寫四層發現的代碼時都是使用TCP/UDP協議, 但是看了很多的代碼都是用socket來完成的,所以就 來學習一下socket。

 

什麼是socket

網絡中的兩臺主機之間進行通信,本質上是主機中所 運行的進程之間的通信,兩個進程如果需要進行通信 ,最基本的前提是每一個進程要有一個唯一的標識。

在本地進程通信中可以使用PID來唯一標識一個程, 但PID在 本地是唯一,可以用 "IP地+ 協議+端口號" 來組成唯一標識的網絡進程,這就是socket。

無論使用何種網絡協議,最本質上都是在進行數據 的收發,發和收,這兩個動作就是socket處理數據 的主要方式。

socket的工作流程

socket 採用C/S 模式,分爲服務端和客戶端
服務端數據處理流程
創建socket -> 綁定到地址和端口 -> 等待連接 -> 開始通信-> 關閉連接
客戶端數據處理流程
創建socket -> 等待連接 -> 開始通信-> 關閉連接
客戶端沒有綁定地址和端口,是由於客戶端進程採用的是隨機端口,當客戶端要去連接目標時,會由系統自定分配一個端口號和自身ip地址去組合
 

socket_tcp_udp_client_service.py

#!/usr/bin/env python3
#coding=utf-8
import sys
import socket
import time 
import os
import threading


ServerIp='192.168.1.1'
ServerPort=9999


def tcp_client_run(): 
    global ServerIp
    global ServerPort
    print("tcp socket client connect to: ",ServerIp, ServerPort)
    myServerPort=int(ServerPort)
    #創建一個socket的類,socket.AF_INET指的是IPV4,SOCK_STREAM指的是TCP協議,UDP協議對應socket_DRAM
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #連接PC服務器的端口,參數是(IP/域名,端口)
    ServerPort_=(ServerIp,myServerPort)
    # connect_ex是connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常
    s.connect_ex(ServerPort_)
     
    #接受服務器的消息,限制接受大小爲1kb=1024b=128KB
    while True:
        try:
            #接受消息,並打印,解碼用utf-8
            print("Local:OK?")
            print(s.recv(1024).decode('utf-8'))
            time.sleep(1)
            #發送消息,注意用二進制的數據傳輸,因爲發送的實際是一個數據流
            data=(('Client'.encode('utf-8')))
            s.send(data)
        except:
            break
    print("Connection is closed by Server")


 
#定義一個接受和發送數據的函數,5次發送後即在服務器端強行關閉連接。
def tcplink(sock,addr):
    global ServerIp
    print("Accept the new connection from %s:%s"%addr)
    sock.send(b"Welcome!Here is the Sever ")
    n=int(5)
    while n>0:
        data=sock.recv(1024)
        time.sleep(1)
        sock.send(('Server==>I have heard you.{:s}:{:d},{:d} talks remaining\n'.format(addr[0],addr[1],n-1)).encode('utf-8'))
        sock.send(('Server==>You said:{:s}\n'.format(data.decode('utf-8'))).encode('utf-8'))
        n-=1
    sock.close()
    print('Connection from %s is close.'%addr[0])
 
 
def tcp_service_run(): 
    global ServerIp
    global ServerPort
    print("socket tcp service connect to: ",ServerIp, ServerPort)
    #創建socket類的實例,並綁定和監聽,閒置最大連接數爲2.        
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.bind((ServerIp,int(ServerPort)))
    s.listen(2)
    print('server is listening,waiting for connection......')
     
    #創建一個新的進程來處理客戶端的請求
    while True :
        sock,addr=s.accept()
        #注意accept方法得到的是一個socket類和一個端口地址的元組。用print命令很容易驗證。
        print(sock,addr)
        try:
            t=threading.Thread(target=tcplink,args=(sock,addr))
            tname=t.name
            print('Now {:s} is running for connection from {:s}'.format(tname,addr[0]))
            t.start()
        except :
            print("Server is block")
            
 

def udp_client_run():
    global ServerIp
    global ServerPort
    print("udp socket client connect to: ",ServerIp, ServerPort)
    ip_port=(ServerIp,int(ServerPort))
    BUFSIZE=1024
    udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

    while True:
        msg=input('input msg>>: ').strip()
        if not msg:continue

        udp_server_client.sendto(msg.encode('utf-8'),ip_port)

        back_msg,addr=udp_server_client.recvfrom(BUFSIZE)
        print(back_msg.decode('utf-8'),addr)
    
    print("Connection is closed by client")
        
  
def udp_service_run():  
    global ServerIp
    global ServerPort
    print("udp socket service connect to: ",ServerIp, ServerPort)
    ip_port=(ServerIp,int(ServerPort))
    BUFSIZE=1024
    udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    udp_server_client.bind(ip_port)

    while True:
        msg,addr=udp_server_client.recvfrom(BUFSIZE)
        print(msg,addr)

        udp_server_client.sendto(msg.upper(),addr)
        
    print("Connection is closed by service")


if __name__ == '__main__':
    if len(sys.argv) == 3 :
        ServerIp=sys.argv[1] 
        ServerPort=sys.argv[2]

        serviceType=input('is client or service?: ').strip()
        protocolType=input('is tcp or udp?: ').strip()
        if protocolType=='tcp':
            if serviceType=='client':
                tcp_client_run()
            else:
                tcp_service_run()
                
        else:
            if serviceType=='client':
                udp_client_run()
            else:
                udp_service_run()
        
    else: 
        print("Use: python3 tcp_client.py 192.168.1.1 9999")
    
    
    
    

 

 

客戶端和服務端都執行 python3 tcp_client.py 192.168.1.1 9999來測試,選擇是客戶端還是服務器,tcp還是udp

 

之後可以正常通信。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章