[TOC]
TCP 3ウェイハンドシェイクプロトコルは、4つが手を振って、ソケットスティックパッケージ
TCPプロトコル
1.契約は、双方向のパイプラインを確立することです
トランスポート層:
-TCPプロトコル
-udp合意
1.1スリーウェイハンドシェイク、ビルドのリンク
1.クライアントは、サーバーへのリンクを確立するための要求を送信します。
2.サーバーは、クライアントに要求された情報を返し、接続を確立するために、クライアントの要求を送信します。
3.クライアントは、双方向の接続を完了するために、復帰することにより、サービス層への接続に成功を送信したサービス要求を受け取ります。
1.2フィードバック機構
1.クライアントがサーバに要求を送信し、サーバが応答を返す必要があります。
2.要求を受信し、サービスも、クライアント側の色データに返されるクライアントに知らせます。
C ----> S:要求は、応答時間を持っている必要があります
短所:
- 洪水攻撃:
サーバが相手にリクエストを送信し、鍛造により多数の要求を指します。
他のサーバーにつながることは麻痺していることに追いつくために使用したいと思います。
Linuxシステム・パラメータは、制限することができます
- セミ接続プールは聞く:時間ユーザー制限の同期間における訪問回数を。
1.3つ振って、切断
1.クライアントが切断に接続されたサーバに要求を送信します。
2.サーバーは、クライアントに情報を返す要求を受信します。
クライアントに送信し、データ送信が完了し、後のすべてのサーバーが接続を切断する要求に同意していることを確認します。3.。
4.クライアントは、サーバに受信した要求切断接続を返します。
ソケット
- 定義:
また、ソケットとして知られているソケットモジュールは、(アプリケーション層より下の層)は、インターネット・プロトコルをカプセル化します
- 役割:
-socketインターネットプロトコルは、アプリケーション層の下にワーキング層を達成することができます。
- 開発効率を向上させるために
- どのように使用します:
輸入ソケット
ソケットソケットを書きます
クライアント
サーバー
注意:
ポート:ポートは、PCのコンピュータ上の特定のソフトウェアを識別します
-0-1024と操作に基づいて、禁止
- 固定ポートソフトウェアを使用しないでください。
ジャンゴ:8000
mysqlの:3306
フラスコ:5000
繰り返し:6379
Tomcatの:8080
MongoDBの:27017
以下は、ソケットの総放出量であります
まずクライアント実行サーバを実行するために行きます
'''
注意:客户端先发一次发送,服务端的先一次接受,再发送信息 server
'''
import socket
#买手机 socket 也是一个类
server = socket.socket()
#绑定手机卡
server.bind(
('127.0.0.1',9528)
)#####127.0.0.1 是本地的回环地址
####局域网内测试的是192.168.12.202 ,9527
#半连接池
server.listen(5)##按照今天举得例子,最多5个人坐椅子,一个人在享受服务,实际是6个人
print('server is running....')
#循环实现可接受多个用户访问
#等待电话接入————>接入客户端
#conn 指的是服务端往客户端的管道
while True:
conn,addr = server.accept()
print(addr)
#循环实现通信
while True:
try: #监听代码块是否有异常
#接收对方讲话的内容
#data客户端端发来的信息
data = conn.recv(1024) #一次可以接收1024bytes
if len(data) == 0:
break
if data.decode('utf-8') =='q':
break
print(data.decode('utf-8')) ###这个是传过来的时候是编码用utf-8编码的,解码也要用这个解码
send_data = input('服务端>>>:')
#服务端往客户端发送信息
conn.send(send_data.encode('utf-8'))
#捕获异常的信息,并打印,报错信息
except Exception as e:
print(e)
break
#挂电话
conn.close()
下面这个是client
# '''
# 启动服务端后再启动客户端
# '''
import socket
#买手机
client = socket.socket()
#拨号
client.connect(
('127.0.0.1',9528)
)#客户端的ip和port必须和服务器保持一致
print('client is running....')
#必须发送bytes类型的数据
#必须讲给对方听
while True:
send_data = input('客户端>>>>:')
client.send(send_data.encode('utf -8'))
data = client.recv(1024)
if data .decode('utf-8') == 'q':
break
if len(data) == 0:
break
print(data.decode('utf-8'))
client.close()
スティックのパッケージの問題
新興の問題:
1.相手によって送信されたデータのサイズを確認していません
2.在发送数据间隔短并且数量小的情况下,会将所有数据一次性发送
解决办法
-粘包(struct模块)
-无论那一端发送数据
-客户端:
1.先制作报头,在发生
2.发送真实的数据
-服务端
1.接收报头,并解包获取真实的长度 recv(报头)
2.根据真实的长度,接收真实的数据 recv(真实的数据长度)
粘包的举例 电影
先执行server 再去执行client
下面这个server
import socket
import json
import struct
server = socket.socket()
server.bind(
('127.0.0.1',9002)
)
server.listen(5)
while True:
conn,addr = server.accept()
print(addr)
while True:
try:
#获取客户传过来的报头
header = conn.recv(4)
#解包获取真实的数据长度
json_len = struct.unpack('i',header)[0]
#接收json的真实长度
json_bytes_data = conn.recv(json_len)
#将bytes类型转化成json数据
json_data = json_bytes_data.decode('utf-8')
#反序列化
back_dic = json.loads(json_data)
print(back_dic)
print(back_dic.get('movie_len'))
# movie_data = conn.recv(back_dic.get('movie_len'))
# print(movie_data)
except Exception as e:
print(e)
break
conn.close()
>>>>>>>>>>>>>>>>>>>>>
('127.0.0.1', 53140)
{'movie_name': '太阳', 'movie_len': 100000}
100000
{'movie_name': '中国', 'movie_len': 100000}
100000
下面这个是client
import socket
import struct
import json
client = socket.socket()
client.connect(
('127.0.0.1',9002)
)
while True:
movie_name = input('请输入电影的名字:')
#伪装的一个电影的真实长度
movie_len = 100000
send_dic = {
'movie_name': movie_name,
'movie_len': movie_len
}
#序列化
json1 = json.dumps(send_dic)
print(json1)
print(json1.encode('utf-8'))
print(len(json1.encode('utf-8')))
json1_bytes = json1.encode('utf-8')
#做一个报头
header = struct.pack('i',len(json1_bytes))
#先发送包头
client.send(header)
#再发送真实的数据
client.send(json1_bytes)
>>>>>>>>>>>>>>>>>>>>>>
请输入电影的名字:太阳
{"movie_name": "\u592a\u9633", "movie_len": 100000}
b'{"movie_name": "\\u592a\\u9633", "movie_len": 100000}'
51
请输入电影的名字:中国
{"movie_name": "\u4e2d\u56fd", "movie_len": 100000}
b'{"movie_name": "\\u4e2d\\u56fd", "movie_len": 100000}'
51
与终端的相关联的举例
下面这个是server
import socket
import subprocess
server = socket.socket()
server.bind(
('127.0.0.1',9000)
)
server.listen(5)
while True:
conn,addr = server.accept()
while True:
try:
cmd = conn.recv(10)
if len(cmd) == 0:
continue
cmd = cmd.decode('utf-8')
if cmd == 'q':
break
#调用subprocess连接终端,对终端进行操作,并获取操作后正确或者错误的结果
obj = subprocess.Popen(
cmd,shell = True,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
)
#结果交给result变量名
result = obj.stdout.read()+obj.stderr.read()####stuout是正确的结果,stuerr是错误的结果,这个result 是正确的和错误的相加,无论对错都能打印一个结果
print(len(result))
#gbk
print(result.decode('gbk')) ###window系统 终端默认的编码是gbk
conn.send(result)
except Exception as e:
print(e)
break
下面这个是client
import socket
client = socket.socket()
client.connect(
('127.0.0.1',9000)
)
while True:
cmd = input('客户输入的内容:')
client.send(cmd.encode('utf-8'))
data = client.recv(19190)
print(len(data))
print(data.decode('gbk'))