socket編程

1.socket編程的概念

  • socket一般也稱做"套接字",用於描述IP地址和端口,是一個通訊鏈的句柄,應用程序一般經過"套接字"向網絡發出請求或者應答網絡請求;html

  • socket起源於Unix,而Unix/Linux基本哲學之一就是「一切皆文件」,socket就是該模式的一個實現,socket便是一種特殊的文件,一些socket函數就是對其進行的操做;編程

  • 線程之間的通訊形式有:event時間lock鎖信號量queue隊列等,而進程之間的通訊,通常使用套接字,套接字的IPC方式使得跨平臺之間的進程通訊成爲可能,最先的socket是在BSD-Unix平臺上發佈,最終成爲了行業標準,使得計算機之間的通訊變得很是簡單;緩存

# 客戶端示例代碼

import socket
# socket.AF_INET, socket.SOCK_STREAM默認參數
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_instance.connect(('www.baidu.com', 80))

2.socket( )類詳解

  • 套接字格式:socket(family, type[,protocal])使用給定的套接字、套接字類型、協議編號(默認爲0)來建立套接字 ;服務器

  • socket.AF_UNIX:用於同一臺機器上的進程通訊(既本機通訊);網絡

  • socket.AF_INET:用於服務器與服務器之間的網絡通訊;socket

  • socket.AF_INET6:基於IPV6方式的服務器與服務器之間的網絡通訊;函數

  • socket.SOCK_STREAM:基於TCP的流式socket通訊;編碼

  • socket.SOCK_DGRAM:基於UDP的數據報式socket通訊;操作系統

  • socket.SOCK_RAW:原始套接字,普通的套接字沒法處理ICMP、IGMP等網絡報文,而SOCK_RAW能夠,其次SOCK_RAW也能夠處理特殊的IPV4報文,此外,利用原始套接字,能夠經過IP_HDRINCL套接字選項由用戶構造IP頭;線程

  • socket.SOCK_SEQPACKET:可靠的連續數據包服務;

3.如何編寫服務器socket端

接下來咱們講解一下TCP服務端和TCP客戶端代碼示例,你們記得看代碼的註釋,方便你們理解代碼:

# TCP服務端代碼示例

import socket
from pprint import pprint

# 建立TCP鏈接
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind方法的參數是ip和端口組成的元組表示address
socket_instance.bind(('127.0.0.1', 9000))

# 操做系統能夠掛起的最大鏈接數,若是同一時間的鏈接數超過5,拒絕其餘的鏈接
socket_instance.listen(5)

# 死循環,循環接收新的客戶端鏈接
while True:
    # 接收客戶端的請求,且獲取新socket對象和客戶端信息
    new_socket, client_addr = socket_instance.accept()  # 阻塞,等待握手

    # 循環接收已鏈接的客戶端發送的數據
    while True:
        # 從緩存區中讀取1024字節信息 ,使用decode()方法進行解碼
        data = new_socket.recv(1024).decode()   # 阻塞的
        # 返回客戶端的一下信息
        pprint(data)
        # 返回客戶端地址 ('127.0.0.1', 51978)
        pprint(client_addr)
        # 把服務器的數據發送回客戶端,使用encode()方法把字符串編碼成二進制
        new_socket.sendall('服務器端已經拿到你的消息'.encode())
# TCP客戶端代碼實現

import socket
# 建立TCP鏈接
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_instance.connect(('127.0.0.1', 9000))   # 進行三次握手
while True:
    cmd = input("請輸入您想說的話:")
    socket_instance.send(cmd.encode())   # 把數據發送到服務端
    data = socket_instance.recv(1024)  
    print(data.decode())

如今咱們已經把TCP的服務端和客戶端都寫好了(寫在兩個不一樣的.py文件中),那咱們來運行代碼看一下效果,首先運行服務器端代碼的.py文件(鼠標右鍵->Run test.py),而後再運行客戶端代碼(鼠標右鍵->Run test1.py),客戶端會提示要咱們輸入想說的話,如圖: 客戶端打印.jpg 服務端打印.jpg

須要注意的是咱們不能經過TCP的客戶端鏈接UDP服務器,也不能經過UDP的客戶端鏈接TCP的服務器,也就是客戶端和服務端的socket協議必須同樣

4.UDP服務器和客戶端端代碼實現

# UDP服務器端代碼實現

import socket
# 建立UDP鏈接
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket_instance.bind(('127.0.0.1', 9000))

# 循環接收新的客戶端鏈接
while True:
    # 接收客戶端的請求,且獲取新socket對象和客戶端信息
    data, client_addr = socket_instance.recvfrom(1024)
    print(data.decode())
    socket_instance.sendto('Server has receive your data'.encode(), client_addr)
# UDP客戶端代碼實現

import socket

# 建立socket實例
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while True:
    data = input("請輸入您想說的話:")
    socket_instance.sendto(data.encode(), ('127.0.0.1', 9000))
    data, server_addr = socket_instance.recvfrom(1024)
    print(data.decode())

而後依次運行服務器端代碼和客戶端代碼,步驟和TCP中的運行差很少

5.UDP 服務器端的實現步驟

1.建立 socket 對象;

2.向socket 對象綁定服務器地址;

3.進入與客戶端交互數據的循環階段;

4.接收客戶端發來的數據(包括 bytes 對象 data,以及客戶端的 IP 地址和端口號 addr,其中 addr 爲二元組 (host, port);

5.打印接收信息,表示從地址爲 addr 的客戶端接收到數據);

6.關閉;

6.UDP客戶端的實現步驟

1.建立 socket 對象;

2.初始化 UDP 服務器的地址;

3.進入與服務器交互數據的循環階段;

4.等待用戶輸入數據;

5.向服務器端發送接收數據;

6.關閉套接字,再也不向服務器發送數據;

7.TCP 和UDP的區別有哪些

  • TCP傳輸數據使用字節流的方式傳輸,而UDP是數據報傳輸;

  • TCP對網絡條件要求高,而UDP更適合實時傳輸;

  • TCP編程能夠保證傳輸的可靠性,UDP則不保證;

  • TCP會產生粘包現象,而UDP則容易丟包;

  • TCP使用listen方法和accpet方法,而UDP不須要;

  • TCP使用recv方法和send方法,而UDP使用recvfrom方法和sendto方法;

8.服務器端socket實例對象建立鏈接的方法有:

  • bind():將套接字綁定到地址,在AF_INET下,以tuple(host, port)的方式傳入;

  • listen():開始監聽TCP傳入鏈接;

  • accept():接受TCP連接並返回(new_socket, address),其中new_socket是新的套接字對象,能夠用來接收和發送數據,address是連接客戶端的地址;

9.客戶端socket實例對象建立鏈接的方法有:

  • connect():鏈接到address處的套接字,通常address的格式爲tuple(host, port),若是連接出錯,則返回socket.error錯誤;

  • connect_ex():功能與s.connect(address)相同,但成功返回0,失敗返回errno的值;

10.客戶端和服務器端socket實例對象都有的方法:

  • recv():接受TCP套接字的數據,數據以字符串形式返回;

  • send():發送TCP數據,將字符串中的數據發送到連接的套接字,返回值是要發送的字節數量,該數量可能小於string的字節大小;

  • sendall():完整發送TCP數據,將字符串中的數據發送到連接的套接字,但在返回以前嘗試發送全部數據,成功返回None,失敗則拋出異常;

  • recvfrom():接受UDP套接字的數據;

  • sendto():發送UDP數據,將數據發送到套接字;

  • close():關閉套接字;

  • getpeername():返回套接字的遠程地址;

  • getsockname():返回套接字本身的地址;

  • settimeout():設置套接字操做的超時時間;

  • gettimeout():返回當前超時值,單位是秒,若是沒有設置超時則返回None;

  • fileno():返回套接字的文件描述;

  • setblocking():若是flag爲0,則將套接字設置爲非阻塞模式,不然將套接字設置爲阻塞模式(默認值);

  • makefile():建立一個與該套接字相關的文件;

  • setsockopt():設置給定套接字選項的值;

  • getsockopt():返回套接字選項的值;

參考:https://www.9xkd.com/user/plan-view.html?id=1374569434

相關文章
相關標籤/搜索