socket套接字編程 HTTP協議

socket套接字編程
 
套接字介紹
 
1. 套接字 : 實現網絡編程進行數據傳輸的一種技術手段
 
2. Python實現套接字編程:import  socket
 
3. 套接字分類
>流式套接字(SOCK_STREAM): 以字節流方式傳輸數據,實現tcp網絡傳輸方案。(面向鏈接--tcp協議--可靠的--流式套接字)
 
>數據報套接字(SOCK_DGRAM):以數據報形式傳輸數據,實現udp網絡傳輸方案。(無鏈接--udp協議--不可靠--數據報套接字)
 
html

 

 


 tcp套接字編程
 
服務端流程
 
python

 1 from socket import * 
 2 
 3 #建立流式套接字
 4 sockfd = socket(AF_INET,SOCK_STREAM,0)
 5 
 6 #綁定IP端口
 7 sockfd.bind(('127.0.0.1',8888))
 8 
 9 #設置監聽套接字,建立監聽隊列
10 sockfd.listen(5)
11 
12 while True:
13     print("waiting for connect....")
14     #等待客戶端連接
15     connfd,addr = sockfd.accept()
16     print("connect from",addr)
17 
18     while True:
19         #收發消息
20     
21         data = connfd.recv(1024)
22 
23         if not data:
24             break   
25         
26         print(data.decode())
27 
28         #發消息
29         connfd.send('來,確認下眼神'.encode())
30     #關閉套接字
31     connfd.close()
32 
33 sockfd.close()
TCP_server.py

 

 


 
1. 建立套接字
sockfd=socket.socket(socket_family=AF_INET,socket_type=SOCK_STREAM,proto=0)
功能:建立套接字
參數:  socket_family  網絡地址類型 AF_INET表示ipv4
    socket_type  套接字類型 SOCK_STREAM(流式)  SOCK_DGRAM(數據報)
    proto  一般爲0  選擇子協議
返回值: 套接字對象

2. 綁定地址
>本地地址 : 'localhost' , '127.0.0.1'
>網絡地址 : '172.40.91.185'
>自動獲取地址: '0.0.0.0'
 

sockfd.bind(addr)
功能: 綁定本機網絡地址
參數: 二元元組 (ip,port)  ('0.0.0.0',8888)
```
 
3. 設置監聽
sockfd.listen(n)
功能 : 將套接字設置爲監聽套接字,肯定監聽隊列大小
參數 : 監聽隊列大小
```
4. 等待處理客戶端鏈接請求
connfd,addr = sockfd.accept()
功能: 阻塞等待處理客戶端請求
返回值: connfd  客戶端鏈接套接字
         addr  鏈接的客戶端地址
```
5. 消息收發
data = connfd.recv(buffersize)
功能 : 接受客戶端消息
參數 :每次最多接收消息的大小
返回值: 接收到的內容
 
n = connfd.send(data)
功能 : 發送消息
參數 :要發送的內容  bytes格式
返回值: 發送的字節數
```
            
6. 關閉套接字 
sockfd.close()
功能:關閉套接字
```
 客戶端流程  編程

 1 # 接受的客戶端
 2 
 3 
 4 from socket import * 
 5 
 6 #建立套接字
 7 sockfd = socket(AF_INET,SOCK_STREAM)
 8 
 9 #發起鏈接
10 sockfd.connect(('127.0.0.1',8888))
11 
12 while True:
13     msg = input("發消息>>  ")
14     #發送消息
15     sockfd.send(msg.encode())
16     if not msg:
17         break
18 
19     #接收消息
20     data = sockfd.recv(1024)
21     print(data.decode())
22 
23 # msg = input("Msg>>")
24 # scorfd.send(msg.encode())
25 
26 # data = sockfd.recv(1024)
27 # print(data.decode())
28 
29 #關閉
30 sockfd.close()
TCP_client.py

 



           
1. 建立套接字
>注意:只有相同類型的套接字才能進行通訊
            
2. 請求鏈接 瀏覽器

sockfd.connect(server_addr)
功能:鏈接服務器
參數:元組  服務器地址

3. 收發消息
>注意: 防止兩端都阻塞,recv send要配合
 
4. 關閉套接字
 
 
tcp 套接字數據傳輸特色
 
>* tcp鏈接中當一端退出,另外一端若是阻塞在recv,此時recv會當即返回一個空字串。
 
>* tcp鏈接中若是一端已經不存在,仍然試圖經過send發送則會產生BrokenPipeError
 
>* 一個監聽套接字能夠同時鏈接多個客戶端,也可以重複被鏈接
 
網絡收發緩衝區
 
1. 網絡緩衝區有效的協調了消息的收發速度
2. send和recv實際是向緩衝區發送接收消息,當緩衝區不爲空recv就不會阻塞。
    
 tcp粘包
 
 socket.time.sleep(0.1)
>緣由:tcp以字節流方式傳輸,沒有消息邊界。屢次發送的消息被一次接收,此時就會造成粘包。
 
>影響:若是每次發送內容是一個獨立的含義,須要接收端獨立解析此時粘包會有影響。
 
>處理方法
>>1. 人爲的添加消息邊界
>>2. 控制發送速度
 
 
UDP套接字編程
 
服務端流程
 
 
服務器

 1 from socket import * 
 2 import sys 
 3 from time import ctime 
 4 
 5 
 6 ADDR = ('127.0.0.1',8888)
 7 BUFFERSIZE = 1024
 8 
 9 #建立數據報套接字
10 sockfd = socket(AF_INET,SOCK_DGRAM)
11 #綁定地址
12 sockfd.bind(ADDR)
13 
14 #收發消息
15 while True:
16     data,addr = sockfd.recvfrom(BUFFERSIZE)
17     print('recv from %s:%s'%(addr,data.decode()))
18     sockfd.sendto\
19     (("[%s] 接收到消息"%ctime()).encode(),addr)
20     
21 sockfd.close()
22 
23 
24 
25 
26 #服務端, udp
27 from socket import * 
28 
29 HOST = '127.0.0.1'
30 PORT = 9999
31 ADDR = (HOST, PORT)
32 #建立數據報套接字
33 sockfd = socket(AF_INET,SOCK_DGRAM)
34 #綁定地址
35 sockfd.bind(ADDR)
36 #收發消息
37 while True:
38     data,addr = sockfd.recvfrom(1024)
39     print('Receive from %s:%s' % (addr,data.decode()))
40     # sockfd.sendto(("[%s] 接收到消息"%ctime()).encode(),addr)
41     sockfd.sendto("收到消息".encode(), addr)
42 sockfd.close()
UDP_server.py

 

    
1. 建立數據報套接字
sockfd = socket(AF_INET,SOCK_DGRAM)
2. 綁定地址 
sockfd.bind(addr)
3. 消息收發        
data,addr = sockfd.recvfrom(buffersize)
功能: 接收UDP消息
參數: 每次最多接收多少字節
返回值: data  接收到的內容
    addr  消息發送方地址
 
n = sockfd.sendto(data,addr)
功能: 發送UDP消息
參數: data  發送的內容 bytes格式
    addr  目標地址
返回值:發送的字節數

4. 關閉套接字
sockfd.close() 網絡

客戶端流程
 
app

 1 from socket import * 
 2 import sys 
 3 
 4 #從命令行傳入IP和端口
 5 #python3 udp_server.py 172.60.50.42 8888
 6 if len(sys.argv) < 3:
 7     print('''
 8            argv is error!!!
 9            input as 
10            python3 udp_server.py 172.60.50.42 4260
11            ''')
12 
13 HOST = sys.argv[1]
14 PORT = int(sys.argv[2])
15 ADDR = (HOST,PORT)
16 BUFFERSIZE = 1024
17 
18 #建立數據報套接字
19 sockfd = socket(AF_INET,SOCK_DGRAM)
20 
21 while True:
22     data = input("消息>>")
23     #直接回車退出
24     if not data:
25         break
26     sockfd.sendto(data.encode(),ADDR)
27     data,addr = sockfd.recvfrom(BUFFERSIZE)
28     print('從服務器收到:',data.decode())
29 sockfd.close()
30 
31 
32 #客戶端
33 from socket import * 
34 import sys 
35 
36 #命令行輸入服務器地址
37 if len(sys.argv) < 3:
38     print('''argv is error !!
39         start as
40         python3 udp_client.py 127.0.0.1 8888
41         ''')
42     # raise
43 
44 HOST = sys.argv[1]
45 PORT = int(sys.argv[2])#字符串轉int類型
46 ADDR = (HOST,PORT)
47 
48 #建立數據報套接字
49 sockfd = socket(AF_INET, SOCK_DGRAM)
50 
51 while True:
52     data = input("消息:   ")
53     if not data:
54         break
55     sockfd.sendto(data.encode(),ADDR)
56     data,addr = sockfd.recvfrom(1024)
57     print("從服務端收到: ", data.decode())
58 
59 sockfd.close()
60 
61 # $ python3 udp_client.py 127.0.0.1 8888
62 #要加ip名和端口名才能運行
UDP_client.py

 


1. 建立套接字
2. 收發消息
3. 關閉套接字
---------------
>總結 :tcp套接字和udp套接字編程區別
>>1. 流式套接字是以字節流方式傳輸數據,數據報套接字以數據報形式傳輸
>>2. tcp套接字會有粘包,udp套接字有消息邊界不會粘包
>>3. tcp套接字保證消息的完整性,udp套接字則不能
>>4. tcp套接字依賴listen accept創建鏈接才能收發消息,udp套接字則不須要
>>5. tcp套接字使用send,recv收發消息,udp套接字使用sendto,recvfrom
---------------------  socket

socket套接字屬性 
【1】 sockfd.type  套接字類型
 
【2】 sockfd.family 套接字地址類型
 
【3】 sockfd.getsockname() 獲取套接字綁定地址
 
【4】 sockfd.fileno() 獲取套接字的文件描述符
 
【5】 sockfd.getpeername() 獲取鏈接套接字客戶端地址
 
【6】 sockfd.setsockopt(level,option,value)
        功能:設置套接字選項
        參數: level  選項類別   SOL_SOCKET
            option 具體選項內容
            value  選項值
 
【7】 sockfd.getsockopt(level,option)  
        功能 : 獲取套接字選項值
 
tcp

 


UDP套接字廣播 ide

 1 #廣播接收端   與udp的
 2 
 3 from socket import *
 4 
 5 HOST = ''
 6 PORT = 8880
 7 
 8 #建立數據報套接字
 9 s = socket(AF_INET,SOCK_DGRAM)#加默認參數0變成流式套接字SOCK_STREAM
10 #固定接收端的端口號
11 s.bind((HOST,PORT))
12 #設置套接字能夠接收廣播, 有此後變成與udp不一樣
13 s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)#broadcast
14 #設置套接字保護端口號
15 s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)#reuseaddr
16 
17 
18 # while True:
19 #     try:
20 #         message,addr = s.recvfrom(1024)
21 #         print("從{}獲取信息{}:".\
22 #             format(addr,message.decode()))#decode將「字節流」按照某種規則轉換成'文本'  str變unicode
23 #         s.sendto(b"I am here",addr)
24 #     except (KeyboardInterrupt,SyntaxError):#從終端ctrl+c的錯
25 #         raise
26 #     except Exception as e:
27 #         print(e)
28 
29 # s.close()
30 
31 while True:
32     try:
33         message,addr = s.recvfrom(1024)
34         print("獲取信息: {}".\
35             format(message.decode()))#decode將「字節流」按照某種規則轉換成'文本'  str變unicode
36         s.sendto(b"I am here",addr)
37     except (KeyboardInterrupt,SyntaxError):#從終端ctrl+c的錯
38         raise#raise 引起一個異常
39     except Exception as e:#異常類
40         print(e)
41 
42 s.close()
broadcast_recv.py
 1 # 發送端
 2 
 3 from socket import *
 4 from time import sleep 
 5 
 6 #發送廣播的地址
 7 #<broadcast>
 8 dest = ('176.122.14.255',8880)#端口號9999一致
 9 #建立數據報套接字
10 s = socket(AF_INET,SOCK_DGRAM)#dgram
11 #設置可以發送廣播
12 s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)#broadcast
13 
14 while True:
15     sleep(2)
16     s.sendto("什麼鬼啊aaaaaa啦啦啦啦啦啦啦".encode(),dest)#目標地址
17     data,addr = s.recvfrom(1024)
18     print("Received from %s:%s"%(addr,data.decode()))
19 s.close()
20 
21 # while True:
22 #     data = input('input: ')
23 #     s.sendto(("@鴻182:"+ data).encode(),dest)
24 # s.close()
25 # 局域網聊天室,同端口號
broadcast_send.py

 


* 廣播定義 : 一端發送多點接收
     
* 廣播地址 : 每一個網絡的最大地址爲發送廣播的地址,向該地址發送,則網段內全部主機都能接收。

 


 TCP套接字之HTTP傳輸
 HTTP協議 (超文本傳輸協議)
 
1. 用途 : 網頁獲取,數據的傳輸
 
2. 特色

應用層協議,傳輸層使用tcp傳輸 

簡單,靈活,不少語言都有HTTP專門接口

無狀態,協議不記錄傳輸內容

http1.1 支持持久鏈接,豐富了請求類型
 
3. 網頁請求過程
  1.客戶端(瀏覽器)經過tcp傳輸,發送http請求給服務端
  2.服務端接收到http請求後進行解析
  3.服務端處理請求內容,組織響應內容
  4.服務端將響應內容以http響應格式發送給瀏覽器
  5.瀏覽器接收到響應內容,解析展現

 

HTTP請求(request)

 

  1 """
  2 httpserver v2.0
  3 env: python3.6
  4 io多路複用 和 http訓練
  5 """
  6 
  7 from socket import *
  8 from select import *
  9 
 10 
 11 # 具體功能實現
 12 class HTTPServer:
 13     def __init__(self, host='0.0.0.0', port=8000, dir=None):
 14         self.host = host
 15         self.port = port
 16         self.dir = dir
 17         self.address = (host, port)
 18         # 多路複用列表
 19         self.rlist = []
 20         self.wlist = []
 21         self.xlist = []
 22         # 實例化對象時直接建立套接字
 23         self.create_socket()
 24         self.bind()
 25 
 26     # 建立套接字
 27     def create_socket(self):
 28         self.sockfd = socket()
 29         self.sockfd.setsockopt(SOL_SOCKET,
 30                                SO_REUSEADDR, 1)
 31 
 32     # 綁定地址
 33     def bind(self):
 34         self.sockfd.bind(self.address)
 35 
 36     # 啓動服務
 37     def serve_forever(self):
 38         self.sockfd.listen(3)
 39         print("Listen the port %d" % self.port)
 40         # IO多路複用接收客戶端請求
 41         self.rlist.append(self.sockfd)
 42         while True:
 43             rs, wx, xs = select(self.rlist,
 44                                 self.wlist,
 45                                 self.xlist)
 46             for r in rs:
 47                 if r is self.sockfd:
 48                     c, addr = r.accept()
 49                     self.rlist.append(c)
 50                 else:
 51                     # 處理請求
 52                     self.handle(r)
 53 
 54     def handle(self, connfd):
 55         # 接收HTTP請求
 56         request = connfd.recv(4096)
 57         # 客戶端斷開
 58         if not request:
 59             self.rlist.remove(connfd)
 60             connfd.close()
 61             return
 62         # 提取請求內容 (字節串按行分割)
 63         request_line = request.splitlines()[0]
 64         info = request_line.decode().split(' ')[1]
 65         print(connfd.getpeername(), ':', info)
 66 
 67         # 根據請求內容進行數據整理
 68         # 分爲兩類 1.請求網頁  2.其餘
 69         if info == '/' or info[-5:] == '.html':
 70             self.get_html(connfd, info)
 71         else:
 72             self.get_data(connfd, info)
 73 
 74     # 返回網頁
 75     def get_html(self, connfd, info):
 76         if info == '/':
 77             # 請求主頁
 78             filename = self.dir + "/index.html"
 79         else:
 80             filename = self.dir + info
 81         try:
 82             fd = open(filename)
 83         except Exception:
 84             # 網頁不存在
 85             response = "HTTP/1.1 404 Not Found\r\n"
 86             response += 'Content-Type:text/html\r\n'
 87             response += '\r\n'
 88             response += '<h1>Sorry....</h1>'
 89         else:
 90             # 網頁存在
 91             response = "HTTP/1.1 200 OK\r\n"
 92             response += 'Content-Type:text/html\r\n'
 93             response += '\r\n'
 94             response += fd.read()
 95         finally:
 96             # 將響應發送給瀏覽器
 97             connfd.send(response.encode())
 98 
 99     # 其餘數據
100     def get_data(self, connfd, info):
101         response = "HTTP/1.1 200 OK\r\n"
102         response += 'Content-Type:text/html\r\n'
103         response += '\r\n'
104         response += "<h1>Waiting for httpserver 3.0</h1>"
105         connfd.send(response.encode())
106 
107 
108 # 用戶使用HTTPServer
109 if __name__ == "__main__":
110     """
111     經過 HTTPServer類快速搭建服務,展現本身的網頁
112     """
113     # 用戶決定的參數
114     HOST = '0.0.0.0'
115     PORT = 8000
116     DIR = './static'  # 網頁存儲位置
117 
118     httpd = HTTPServer(HOST, PORT, DIR)  # 實例化對象
119     httpd.serve_forever()  # 啓動服務
HTTP_server.py

 

 1 #靜態網頁處理器
 2 #採用循環的模式,沒法知足客戶端長鏈接
 3 
 4 from socket import *#網絡鏈接端點,導入模塊
 5 
 6 #處理客戶端請求, 交互
 7 def handleClient(connfd):#請求,調用函數
 8     request = connfd.recv(2048)#請求套接字接受文件
 9     # print('**************')
10     # print(request)
11     # print('**************')
12     #按照行切割請求, 方便查看
13     request_lines = request.splitlines()
14     for line in request_lines:
15         print(line.decode())#對分割後的文件解碼
16 
17     try:
18         f = open("index.html")
19     except IOError:#找不到頁面, 文件出錯
20         response = "HTTP/1.1 303 not Found\r\n"#http響應行
21         response += '\r\n'#無響應頭, 有空行
22         response += '''====sorry ,file not find
23                     *******************************
24                     Sorry bing i love you miss you.
25                     *******************************
26                     '''
27     else:#正常狀況運行
28         response = "HTTP/1.1 200 OK\r\n"#成功響應頭, 響應體是頁面
29         response += '\r\n'
30         response += f.read()#響應體是頁面
31         # for i in f:
32         #     response += i
33     finally:
34         connfd.send(response.encode())#發送給瀏覽器
35         connfd.close()
36 
37 #流程控制
38 def main():
39     sockfd = socket()#建立流式套接字
40     sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)#設置端口重用
41     sockfd.bind(('0.0.0.0',8888))#綁定套接字
42     sockfd.listen(10)#監聽套接字
43     while True:#循環監聽等待鏈接
44         print("Listen the port 8000..")
45         connfd,addr = sockfd.accept()#建立另外一個套接字鏈接請求,便於接收一個後再接收,
46         #處理瀏覽器發來的請求
47         handleClient(connfd)#跟客戶頓交互
48         connfd.close()#關閉套接字
49      
50 
51 if __name__ == "__main__":#調用主函數
52     main()
53 
54 
55 # ---------------------------------------------------------------
56 
57 
58 # #接收請求
59 # #查看請求
60 # #返回客戶端請求
61 
62 # def handleClient():
63 #     pass
64 
65 
66 # #建立tcp套接字, 調用handleClient完成功能
67 # def main():
68 #     pass
69 
70 # if __name__=="__main__":
71 #     main()
HTTP_server.py
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>歡迎進入Alan主頁</title>
 6 </head>
 7 <body>
 8     <h1>Alan songzihong welcome to you </h1>
 9     <h1>what is you name</h1>
10     <h1>How can i do cna help you </h1>
11 </body>
12 </html>
13 
14 <!-- 沒保存會只顯示文件名 -->
15 <!-- html:5 + tab -->
16 <!-- h1 + tab -->
index.html

 


* 請求行 : 具體的請求類別和請求內容
 
```
    GET         /        HTTP/1.1
    請求類別   請求內容     協議版本
```
 
請求類別:每一個請求類別表示要作不一樣的事情  
 
```        
        GET : 獲取網絡資源
        POST :提交必定的信息,獲得反饋
        HEAD : 只獲取網絡資源的響應頭
        PUT : 更新服務器資源
        DELETE : 刪除服務器資源
        CONNECT
        TRACE : 測試
        OPTIONS : 獲取服務器性能信息
```
 
* 請求頭:對請求的進一步解釋和描述
```
Accept-Encoding: gzip
```
* 空行
* 請求體: 請求參數或者提交內容


http響應(response)
 
1. 響應格式:響應行,響應頭,空行,響應體
 
* 響應行 : 反饋基本的響應狀況
 
```         
HTTP/1.1     200       OK
版本信息    響應碼   附加信息
```
 
響應碼 :  
```
1xx  提示信息,表示請求被接收
2xx  響應成功
3xx  響應須要進一步操做,重定向
4xx  客戶端錯誤
5xx  服務器錯誤
```
* 響應頭:對響應內容的描述
```             
Content-Type: text/html
```
 
* 響應體:響應的主體內容信息

相關文章
相關標籤/搜索