socket套接字

socket套接字

端口号:

​ 0-1024: 禁用,操作系统在用

​ 用8000以上的

软件固定的端口号:

​ django: 8000

​ mysql: 3306

​ redis: 6379

​ flask: 5000

​ tomcat:8080

​ mongodb:27017

1.TCP协议:三次握手,四次挥手

​ TCP协议建立双向通道

​ 三次握手,建立连接:

​ 1.客户端向服务端发送建立连接的请求

​ 2.服务端返回接收请求的信息给客户端,并且发送送往客户端建立连接的请求

​ 3.客户端接收到服务端发来的请求,返回同意信息给服务端,完成双向连接

反馈机制:

客户端往服务端发送请求,服务端必须返回响应,告诉客户端收到请求了,并且将服务端的数据一并返回给客户端

一次请求必须要有一次响应

缺点:

​ 洪水攻击:

​ 指的是通过伪造大量的请求,往对方服务器发送请求,导致对方服务器响应跟不上,以至于瘫痪

​ 在linux系统中有一个参数可以限制

​ 半连接池listen:限制用户在同一时间段内的访问数量

​ 四次挥手,断开连接

1.客户端向服务端发送断开连接的请求

2.服务端返回收到请求的信息给客户端

3.服务器确认所有的数据接收完成后,再发送同意断开连接的请求给客户端,同时发送断开连接的请求

4.客户端返回同意断开连接的请求,给服务端

socket套接字通信:

什么是socket:

socket是一个模块,又称套接字,用来封装互联网协议(应用层以下的层)

为什么要有socket?

socket可以实现,互联网协议应用层以下的层的工作,提高开发效率

怎么使用socket?

import socket

写socket套接字:

client和server

粘包问题:

1.无法确认对方发过来数据的大小

2.再发送数据间隔短并且数据量小的情况下,会将所有的数据一次性发送

解决: 确认对方数据的大小

解决粘包问题(struct模块)

无论哪一段先发送数据

客户端:

1)先制作报头,并发送(struct)

2)发送真实数据

服务端:

1)接收报头,并解包获取真实数据长度

2)根据真实数据长度接收真实数据

rev(真实数据长度)

server端

import socket

server = socket.socket()

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

# 半连接池
server.listen(5)  # 实际上可以允许6个访问

print(
    'serve is running!'
)

# conn:指的是服务端通往客户端的管道
# 接收客户端链接
conn, addr = server.accept()

print(addr)

# 接收内容
ret = conn.recv(1024)
print(
    ret.decode('utf-8')
)

# 发送数据
conn.send('你好'.encode('utf-8'))

conn.close()


client端

import socket

client = socket.socket()

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

print(
    'client is running!'
)

# 必须发送bytes的数据
# client.send('hello'.encode('utf-8'))
client.send('hello'.encode('utf-8'))

# 接收数据
ret = client.recv(1024)
print(ret.decode('utf-8'))

client.close()


结果:
server端:
serve is running!
('127.0.0.1', 63794)
hello

client端:
client is running!
你好

完整的:

server端

import socket

server = socket.socket()

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

print('server is running!')

# 半连接池
server.listen(5)

# 循环实现可以接受多个用户访问
while True:
    conn, addr = server.accept()
    print(addr)

    while True:
        # 抛出异常处理
        try:
            # 接收客户端发送的数据
            data = conn.recv(1024)
            data = data.decode('utf-8')
            if len(data) == 0:
                break
            if data == 'q':
                break
            print(data)

            # 再由服务端给客户端发送数据
            send_data = input('服务端》》:').strip()
            conn.send(send_data.encode('utf-8'))
        except Exception as e:
            print(e)

    conn.close()
    
client端:

import socket

client = socket.socket()

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

print('client is running!')

while True:
    # 用户输入
    send_data = input('客户端》》:').strip()
    # 客户端发送信息
    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()


运行结果:
client:

client is running!
客户端》》:你是谁
我是你爸爸
客户端》》:去你的
fuck your mouth
客户端》》:

server:

server is running!
('127.0.0.1', 64030)
你是谁
服务端》》:我是你爸爸
去你的
服务端》》:fuck your mouth

解决粘包问题:
client:

import socket
import struct
import json

client = socket.socket()

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

while True:

    movie_name = input('请输入上传电影的名字: ')

    # 伪装电影真实数据
    movie_len = 1000000

    send_dic = {
        'movie_name': movie_name,
        'movie_len': movie_len
    }

    # 序列化
    json = json.dumps(send_dic)
    print(json)
    print(json.encode('utf-8'))
    print(len(json.encode('utf-8')))

    json_bytes = json.encode('utf-8')

    # 做一个报头
    header = struct.pack('i', len(json_bytes))

    # 先发送报头
    client.send(header)

    # 后发送真实数据
    client.send(json_bytes)


server:
    import socket
import json
import struct

server = socket.socket()

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

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(dict)的真实长度
            json_bytes_data = conn.recv(json_len)

            # 将bytes类型数据转为json数据
            json_data = json_bytes_data.decode('utf-8')

            # 反序列化  json ---> dict
            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()

原文地址:https://www.cnblogs.com/godlover/p/11991802.html