socket模块(套接字模块)

socket模块(套接字模块)

一、最简单版本(互传一次就结束)

# 客户端
import socket
client = socket.socket()
client.connect(('127.0.0.1', 8080))  # 8080是端口号
'''
来源百度百科
'127.0.0.1'是本机回还地址,不属于任何一个有类别地址类。它代表设备的本地虚拟接口,所以默认被看作是永远不会宕掉的接口。在Windows操作系统中也有相似的定义,所以通常在安装网卡前就可以ping通这个本地回环地址。一般都会用来检查本地网络协议、基本数据接口等是否正常的。
'''
client.send(b'hello, baby! I love you!')
msg = client.recv(1024)
print(msg.decode('utf-8'))

# 服务端
import socket
server = socket.socket()
server.bind(('127.0.0.1', 8080))  # 服务端绑定ip和端口号
server.listen(5)  # 半连接池,待连接(处于一个队列中)该服务端的客户端数不能超过5个
# 有一个房间,房间内是客户端和服务端,房间外有五张凳子,最多支持5个待连接客户端,再多就会报错
conn,addr = server.accept()
msg = conn.recv(1024)
print(msg.decode('utf-8'))
conn.send(b'I love you too!')

conn.close()  # 关闭连接
server.close()  # 关闭服务器

二、升级版(服务端不间断服务,客户端可以重复发送命令)

# 客户端
import json
import socket
import struct

client = socket.socket()
client.connect(('127.0.0.1', 8080))

while True:
    cmd = input('>>>:').encode('utf-8')
    print(type(cmd))  # <class 'bytes'>
    if len(cmd) == 0:
        continue
    client.send(cmd)
    # 1.接收报头
    header_length = client.recv(4)
    print(type(header_length))  # <class 'bytes'>
    # 2.解包得到字典的长度
    d_length = struct.unpack('i', header_length)[0]
    print(type(d_length))  # <class 'int'>
    # 3.接收字典
    d = client.recv(d_length)
    print(type(d))  # <class 'bytes'>
    # 4.由字典拿到数据的长度
    real_d = json.loads(d)
    print(type(real_d))  # <class 'dict'>
    data_length = real_d['info_length']
    print(data_length)
    print(type(data_length))  # <class 'int'>
    # 5.接收真实数据
    with open('file', 'a', encoding='utf-8') as f:
        real_length = 0
        while real_length < data_length:
            data = client.recv(1024)
            real_length += len(data)
            f.write(data.decode('gbk'))

# 服务端
import json
import socket
import subprocess
import struct
from socket import SOL_SOCKET, SO_REUSEADDR

server = socket.socket()
# 避免因操作系统未及时回收端口造成的端口已被占用的问题
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server.bind(('127.0.0.1', 8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    while True:
        try:
            cmd = conn.recv(1024).decode('utf-8')
            if len(cmd) == 0:
                break
            obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            print(type(obj))
            msg = obj.stdout.read() + obj.stderr.read()
            print(type(msg))  # <class 'bytes'>
            # 1.将数据长度放到字典中,将字典长度打包-报头
            d = {'info_length': len(msg)}
            json_d = json.dumps(d)
            print(type(json_d))  # <class 'str'>
            header = struct.pack('i', len(json_d))
            print(header)  # b'\x15\x00\x00\x00'
            # 2.发送报头
            conn.send(header)
            # 3.发送字典
            conn.send(json_d.encode('utf-8'))
            # 4.发送真实数据
            conn.send(msg)
        except ConnectionResetError:  #
            break
    conn.close()

三、TCP传输的特点

  • 应用程序所需要的数据,都是跟所在的那台计算机内存去要(所有数据传输都遵循这个规则)

  • 会将数据量较小的并且时间间隔比较短的数据一次性打包发送给对方

# 客户端
import socket

client = socket.socket()  # 拿电话
client.connect(('127.0.0.1', 8080))  # 拨号   写的是对方的ip和port

client.send(b'hello')
client.send(b'world')
client.send(b'baby')
client.send(b'baby')

# 服务端
import socket

server = socket.socket()  # 买手机 不传参数默认用的就是TCP协议
server.bind(('127.0.0.1', 8080))  # bind((host,port))  插电话卡  绑定ip和端口
server.listen(5)  # 开机    半连接池

conn, addr = server.accept()  # 接听电话  等着别人给你打电话     阻塞
data = conn.recv(1024)  # 听别人说话 接收1024个字节数据          阻塞
print(data)
data = conn.recv(1024)  # 听别人说话 接收1024个字节数据          阻塞
print(data)
data = conn.recv(1024)  # 听别人说话 接收1024个字节数据          阻塞
print(data)

# 输出内容 理论上应该是在一行显示...
b'hello'
b'worldbabybaby'
b''

四、arp协议

  • 先由IP地址找到对方,然后对方将自己的mac地址发回来

五、粘包问题

  • 假设一种情况

    小明的妈妈给小明零花钱,给了他50块钱,放在了零钱罐中,但都是硬币,小明还小,两只手一次最多只能拿十个硬币,而且规定,小明只有在妈妈给他零花钱的时候才能从零钱罐中拿钱,所以,虽然妈妈每次都给小明50块的零花钱,但是小明实际上每次只能拿到10块钱。

  • 假设另一种情况

    小明和小红在玩一个游戏,游戏规则如下:小红和小明面对面坐在桌子两侧,桌子上有三个罐子,小红小明各有一个,小红手上的罐子里有三个玻璃球,规定小红将自己罐子里的球倒入桌上的空罐子,倒三次;小明在小红将球放入罐子后,拿起罐子,将里面的球倒入自己的罐子中,也倒三次。游戏开始,小红往罐子里倒了球,小明拿起罐子,将球倒入自己的罐子中,发现一次性倒出三个球。他问小红,小红说她一次性讲球全部倒进去了

  • 这两种情况分别是,一次拿少了,一次拿多了

六、解决粘包问题

  • 解决粘包问题的关键在于,每一次拿的量是未知的
  • 那么我们就要设法让服务端知道我们每一次传过去的数据的长度是多少
服务端
    1.先制作一个发送给客户端的字典
    2.制作字典的报头
    3.发送字典的报头
    4.发送字典
    5.再发真实数据
客户端
    1.先接受字典的报头
    2.解析拿到字典的数据长度
    3.接收字典
    4.从字典中获取真实数据的长度
    5.接收真实数据

原文地址:https://www.cnblogs.com/DcentMan/p/11380545.html

时间: 2024-10-07 18:01:30

socket模块(套接字模块)的相关文章

Win2 Socket(套接字)相关 API

Socket(套接字) 作者信息 肖进 单位:南京中萃食品有限公司 资讯部 邮箱:[email protected] 电话:025-58642091 与socket有关的一些函数介绍 1.读取当前错误值:每次发生错误时,如果要对具体问题进行处理,那么就应该调用这个函数取得错误代码. int  WSAGetLastError(void ); #define h_errno   WSAGetLastError() 错误值请自己阅读Winsock2.h. 2.将主机的unsigned long值转换为

学生党 应该去 研究研究 Socket(套接字) 实现原理

学生党 整天 不知所谓,    给你们 找点事 做做,     你们 可以去 研究一下 Socket (套接字) 的 实现原理, 看能不能 自己 实现一个  . Socket  是 操作系统 内核,  由 操作系统 直接调遣  .  为什么 是 操作系统 内核?  因为 Socket 涉及 到 IO,    IO 是 操作系统 的 基本任务, IO 涉及 中断, 所以必须作为 操作系统 内核,  由 操作系统 直接调度    . 多的也不要求了,     你们 去把  Windows Socke

Python之socket(套接字)

Socket 一.概述 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用[打开][读写][关闭]模式来操作.socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭) socket和file的区别: file模块是针

Linux Socket 原始套接字编程

对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发之自己构建协议头.对于原始套接字编程有些细节性的东西还是需要注意的. 1. 原始套接字创建 原始套接字的编程和udp网络编程的流程有点类似,但是原始套接字编程中不需要bind操作,因为在数据接收和发送过程中使用sendto和recvfrom函数实现数据的接收和发送.不过不是说原始套接字不能使用bin

Linux - Socket网络套接字

OSI七层协议功能 物理层 面向物理传输媒体,屏蔽媒体的不同 主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质的传输速率等.它的主要作用是传输比特流(就是由1.0转化为电流强弱来进行传输,到达目的地后在转化为1.0,也就是我们常说的模数转换与数模转换).这一层的数据叫做比特. 链路层 面向一条链路,成帧和无差错传输 主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装.常把这一层的数据叫做帧.在这一层工作的设备是交换机,数据通过交换机来传输. 网络层 分配地址.

socket(套接字)

客户端: 创建套接字(socket) 连接服务器(connect) 通信(send,recv或者write,read) 关闭套接字(closesocket) 示例代码: int main(int argc, char* argv[]) { const int BUF_SIZE = 64; WSADATA wsd; //WSADATA变量 SOCKET sHost; //服务器套接字 SOCKADDR_IN servAddr; //服务器地址 char buf[BUF_SIZE]; //接收数据缓

什么是套接字(Socket)?套接字(Socket)是什么意思?(转)

应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题.多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据.为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口,区分不同应用程序进程间的网络通信和连接. 网络化的应用程序在开始任何通讯之前都必需要创建套接字.就像电话的插口一样,没有它就完全没办法通信. 生成套接字,主要有3个参数:通信的目的IP地址.使用的传输层协议(

【Java TCP/IP Socket】深入剖析socket——TCP套接字的生命周期

建立TCP连接 新的Socket实例创建后,就立即能用于发送和接收数据.也就是说,当Socket实例返回时,它已经连接到了一个远程终端,并通过协议的底层实现完成了TCP消息或握手信息的交换. 客户端连接的建立 Socket构造函数的调用与客户端连接建立时所关联的协议事件之间的关系下图所示: 当客户端以服务器端的互联网地址W.X.Y.Z和端口号Q作为参数,调用Socket的构造函数时,底层实现将创建一个套接字实例,该实例的初始状态是关闭的.TCP开放握手也称为3次握手,这通常包括3条消息:一条从客

socket(套接字)初使用

socket层 socket:是应用层与TCP/IP协议通信的中间软件抽象层,是一组接口,在设计模式中,socket其实就是一个门面模式,它把复杂的TCP/IP协议隐藏在socket接口后面. 基于TCP协议的socket tcp是基于链接,必须先启动服务端,然后在启动客户端去链接服务端 server端 1 import socket 2 sk=socket.socket() 3 sk.bind(('127.0.0.1',9000)) #把地址绑定到套接字 4 sk.listen() #监听链接