Day 28 网络编程2

网络编程2

TCP三次握手和四次挥手

TCP协议

tcp把链接作为最基本的对象,每一条TCP链接都有两个端点,这种端点我们叫做套接字(socket),它的定义为端口号拼接到IP地址即构成了套接字.

TCP链接的建立-三次握手

如果客户端需要到服务端下载数据,客户端和服务端必须建立链接,这个链接就是三次握手

  • 最开始的时候客户端和服务端都是处理关闭状态的,客户端主动打开,服务端被动打开
  1. 客户端会向服务端发起一个请求,里面会有一个SYN报头
  2. 服务端收到客户端的请求后,会响应客户端,并且把SYN报头改装后返回客户端,并且还有一个ACK报头
  3. 客户端收到服务端的响应后开始进入建立连接状态,再发一条请求,请求带上ACK给服务端,让服务端也进入连接状态

为什么要用三次握手

  • 一次

客户端直接进入连接状态,发送请求给服务端进入连接状态

缺点:服务端收到请求后,无法找到对应的客户端

  • 两次
  1. 客户端暂不进入连接状态,发送一条请求给服务端
  2. 服务端直接进入连接状态,发送一条确认请求给客户端,客户端收到后直接进去连接状态

缺点:服务端收到客户端的请求后,进入连接状态,占用一个端口,如发送请求后客户端未响应,则端口占用短期内一直存在,黑客可以通过此种原理伪造虚拟客户端发起请求,短时间内大量占用服务端的端口,造成服务器宕机,因此2次握手存在风险

TCP链接的结束-四次挥手

  • 数据传输完毕后,双方都需要释放链接,最开始的时候,客户端和服务端都是处于established状态,然后客户端主动关闭,服务器端被动关闭
  1. 客户端会发送请求带上FIN报头给服务端,要求断开链接
  2. 服务端接收到客户端的请求后,返回一个带有ACK报头的请求表示已经确认了(此时FIN报头没有返回,并且服务端还有可能需要传输部分数据)
  3. 服务端数据传输结束之后,,服务端又会发送一次带报头FIN的请求,告诉客户端这边数据已经发送完了,需要客户端确认
  4. 客户端收到服务端的确认请求后,回复贷后ACK的报头,告知服务端关闭链接,同时经过一定时间后客户端自行关闭(2msl)
  • 如果只有三次链接,但是客户端可能在第二次连接后就挂掉了,客户端没有收到第2-3步之间的数据传输

客户端+服务端实现聊天功能

服务端

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind(('127.0.0.1', 8000))

server.listen(5)

print('start...')

while True:
    conn, client_address = server.accept()

    username = conn.recv(1024)
    username = username.decode('utf-8')

    while True:
        data = conn.recv(1024)
        data = data.decode('utf-8')

        print(f'{username}:{data}')

        msg = input('输入:')

        conn.send(msg.encode('utf-8'))

客户端

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

client.connect(('127.0.0.1', 8000))

username = input('请输入您的用户名')
client.send(username.encode('utf-8'))

while True:
    msg = input('请输入:')

    client.send(msg.encode('utf-8'))

    data = client.recv(1024)
    data = data.decode('utf-8')

    print(f'淘宝客服助手:{data}')

SSH服务端和客户端

ssh服务端

import socket, subprocess

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind(('192.168.11.34', 8002))
server.listen(5)

print('start...')

while True:
    conn, client_address = server.accept()
    print(client_address)

    while True:
        cmd = conn.recv(1024)
        cmd = cmd.decode('utf-8')
        print(cmd)

        pipeline = subprocess.Popen(cmd,
                                    shell=True,
                                    stderr=subprocess.PIPE,
                                    stdout=subprocess.PIPE)

        stderr = pipeline.stderr.read()
        stdout = pipeline.stdout.read()

        conn.send(stderr)
        conn.send(stdout)

ssh客户端

import socket

client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client.connect(('192.168.11.34',8002))

while True:
    cmd=input('请输入命令')
    client.send(cmd.encode('utf-8'))

    data=client.recv(10240)
    print(data.decode('gbk'))# 因为通过subprocess执行的命令字符编码随系统,所以解码要用gbk

猜你喜欢

转载自www.cnblogs.com/masterjian924/p/11094531.html
今日推荐