网络编程详解

1.什么是socket

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,
它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。 所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。 也有人将socket说成ip+port,ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的一个应用程序,ip地址是配置到网卡上的,
而port是应用程序开启的,ip与port的绑定就标识了互联网中独一无二的一个应用程序 而程序的pid是同一台机器上不同进程或者线程的标识

借助一张图来解释

 

2.套接字的工作流程

一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。

等交流结束,挂断电话结束此次交谈。 生活中的场景就解释了这工作原理。

 

 

 3.简单sockect通信

server端

'''
先启动套接字服务端
'''
import socket

# 买手机     # 默认tcp协议:socket.AF_INET,socket.SOCK_STREAM     udp协议:socket.AF_INET,socket.SOCK_DGRAM
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 绑定手机卡
server.bind(
    # 相当于手机号码
    # 127.0.0.1 == localhost 本机回环地址
    # 单机测试下: 127.0.0.1
    ('127.0.0.1', 9527)
)

# 半连接池  最大监听数,同一时间可以有多个电话打进来,但是只能连接一个
server.listen(5)
# 等待电话连接(阻塞态)
# server.accept()是个元组   conn:连接对象,addr:客户端的连接和端口
conn, addr = server.accept()

# 接听对方讲话的内容
# data客户端发送过来的消息
data = conn.recv(1024)  # 可接受一次1024bytes的数据
print(data)
#服务端回话
conn.send(b'hello')
# 挂电话 conn.close() #关手机 # server.close()

client端

import socket

# 买手机
client = socket.socket()

# 拨号
client.connect(
    # 客户端的ip与port必须与服务端一致
    ('127.0.0.1', 9527)
)

# 必须发送bytes类型的数据

# 讲话给对方听
client.send(b'hello')
#客户端接收
client.recv(1024)

4.解决粘包问题

粘包问题:在发送数据小,时间间隔短,会放到一个包中发送, 所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

解决:发多少,收多少,先发报头 告知数据大小    struct模块    

发送时:

先发报头长度

再编码报头内容然后发送

最后发真实内容

 

接收时:

先手报头长度,用struct取出来

根据取出的长度收取报头内容,然后解码,反序列化

从反序列化的结果中取出待取数据的详细信息,然后去取真实的数据内容

client

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
import socket,time,struct

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(('127.0.0.1',8080))

while True:
    msg=input('>>: ').strip()
    if len(msg) == 0:continue
    if msg == 'quit':break

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



    l=s.recv(4)
    x=struct.unpack('i',l)[0]
    print(type(x),x)
    # print(struct.unpack('I',l))
    r_s=0
    data=b''
    while r_s < x:
        r_d=s.recv(1024)
        data+=r_d
        r_s+=len(r_d)

    # print(data.decode('utf-8'))
    print(data.decode('gbk')) #windows默认gbk编码

客户端(自定制报头)
View Code

server

import socket,struct,json
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加

phone.bind(('127.0.0.1',8080))

phone.listen(5)

while True:
    conn,addr=phone.accept()
    while True:
        cmd=conn.recv(1024)
        if not cmd:break
        print('cmd: %s' %cmd)

        res=subprocess.Popen(cmd.decode('utf-8'),
                             shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        err=res.stderr.read()
        print(err)
        if err:
            back_msg=err
        else:
            back_msg=res.stdout.read()


        conn.send(struct.pack('i',len(back_msg))) #先发back_msg的长度
        conn.sendall(back_msg) #在发真实的内容

    conn.close()

服务端(自定制报头)
View Code

 

 

udp套接字: 无连接的

server

 

 client

 

posted @ 2019-12-08 00:49  躺云飘  阅读(149)  评论(0编辑  收藏  举报