zoukankan      html  css  js  c++  java
  • 网络编程之Socket

    一.Socket层

    Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.
    把复杂的TCP/IP协议族隐藏在Socket接口后面.让Socket去组织数据,以符合指定的协议
    可以理解socket就是一个模块,也可理解成ip+port
    只要确立了ip和port就能找到一个应用程序,并且使用socket模块来与之通信

    2.套接字(socket):

    一开始,套接字被设计用在同一台主机上多个应用程序之间的通讯
    套接字有两种:
    基于文件型:套接字家族的名字:AF_UNIX
    基于网络型:套接字家族的名字:AF_INET

    3.socket参数

    socket.socket(family=AF_INET,type=SOCK_STREAM,proto=0,fileno=None)
    创建socket对象的参数说明:
    SOCK_STREAM 是基于TCP的,有保障的(即能保证数据正确传送到对方)面向连接的SOCKET,多用于资料传送。
    SOCK_DGRAM 是基于UDP的,无保障的面向消息的socket,多用于在网络上发广播信息。
    proto 协议号通常为零,可以省略。
    fileno 如果指定了fileno,则其他参数将被忽略,导致带有指定文件描述符的套接字返回。

    4.服务端套接字函数

    s.bind()     绑定(主机,端口号)到套接字
    s.listen() 开始TCP监听
    s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来
    客户端套接字函数:s.connect() 主动初始化TCP服务器连接

    5.公共用途的套接字函数:

    s.recv()    接收TCP数据
    s.send() 发送TCP数据(待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
    s.sendall()发送完整的TCP数据(待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
    s.recvfrom() 接收UDP数据
    s.sendto() 发送UDP数据
    s.getsockname() 当前套接字的地址
    s.close() 关闭套接字

    ####
    阻塞####
    阻塞:如果阻塞模式则等待数据
    非阻塞:如果非阻塞模式有数据返回数据、无数据直接返回报错
    UDP中服务端有几个recvfrom就要对应几个sendinto
    sk.setblocking(bool)
    是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错

    二.基于TCP协议的socket

    tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端
    简单通信:server端
    import socket
    sk=socket.socket()   #创建了一个socket对象
    #sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 如果端口冲突加上这个
    sk.bind(('127.0.0.1',9000))  #绑定一台机器的(ip,端口)
    sk.listen()          ##建立监听等待别人连接
    corn,add=sk.accept() #阻塞:在这里等待直到接到一个连接
    # conn是连接
    # addr是对方的地址
    corn.send(b'hello') #和对方打招呼
    msg=corn.recv(1024)  #接收对方的信息
    print(msg)
    corn.close()  #关掉连接
    sk.close()
    View Code

    client端

    import socket
    sk=socket.socket()
    sk.connect(("127.0.0.1",9000))
    ret=sk.recv(1024)
    print(ret)
    sk.send(b'HELLO')
    sk.close()
    View Code

    简单的聊天例子:server端

    import socket
    sk=socket.socket()
    sk.bind(('127.0.0.1',9000))
    sk.listen()
    corn,add=sk.accept()
    while True:
        inp=input("《《")
        if inp == "q":
            corn.send(inp.encode("utf-8"))
            break
        corn.send(inp.encode("utf-8"))
        msg=corn.recv(1024)
        if msg.decode("utf-8") =="q":break
        print(msg.decode("utf-8"))
    corn.close()
    sk.close()
    View Code

    client端

    import socket
    sk=socket.socket()
    sk.connect(("127.0.0.1",9000))
    while True:
        ret=sk.recv(1024)
        if ret.decode("utf-8") == "q":break
        print(ret.decode("utf-8"))
        sed=input("<<")
        if sed.encode(("utf-8")) == "q":
            sk.send(sed.encode(("utf-8")))
            break
        sk.send(sed.encode(("utf-8")))
    sk.close()
    
    

    三.基于UDP协议的socket

    udp是无链接的,先启动哪一端都不会报错

    简单通信:server端

    import socket
    sk=socket.socket(type=socket.SOCK_DGRAM)
    # 建立一个socket对象,指定以UDP协议的形式来连接
    sk.bind(("127.0.0.1",9000)) # 指定服务的地址
    msg,add=sk.recvfrom(1024) # 接收消息,发送端的地址
    print(msg)
    sk.sendto(b'hello',add)  #给发送端回复消息
    sk.close() #关闭socket连接
    View Code

    client端

    
    
    import socket
    sk=socket.socket(type=socket.SOCK_DGRAM)
    sk.sendto(b"HELLO",("127.0.0.1",9000))  ##直接给服务器发送一段消息
    msg,add=sk.recvfrom(1024)  # #接收对面的回信
    print(msg)
    sk.close()
    View Code
    
    
    简单的聊天例子:server端
    import socket
    sk=socket.socket(type=socket.SOCK_DGRAM)
    sk.bind(("127.0.0.1",9000))
    while True:
        msg,add=sk.recvfrom(1024)
        print("来自%s的一条消息:%s"%(add,msg.decode("utf-8")))
        message=input("》》")
        sk.sendto(message.encode("utf-8"),add)
    sk.close()
    View Code
    
    

    client端

    import socket
    sk=socket.socket(type=socket.SOCK_DGRAM)
    while True:
        message = input("》》")
        add=("127.0.0.1",9000)
        sk.sendto(message.encode("utf-8"), add)
        msg,add=sk.recvfrom(1024)
        print(msg.decode("utf-8"))
    sk.close()
    View Code
    时间服务器:客户端每隔一段时间发送请求到服务端,发送时间的格式
    简单通信:server端
    import time
    import socket
    sk=socket.socket(type=socket.SOCK_DGRAM)
    sk.bind(("127.0.0.1",9000))
    while True:
        msg,add=sk.recvfrom(1024)
        msg=time.strftime(msg.decode("utf-8"))
        sk.sendto( msg.encode("utf-8"),add)
    sk.close()
    View Code
    
    

    client端

    import time
    import socket
    sk=socket.socket(type=socket.SOCK_DGRAM)
    while True:
        add=("127.0.0.1",9000)
        msg_time="%Y-%m-%d %H:%M:%S"
        sk.sendto(msg_time.encode("utf-8"),add)
        msg,add=sk.recvfrom(1024)
        print(msg.decode("utf-8"))
        time.sleep(1)
    sk.close()
    View Code
     
     
     
     
     
     
    
    
  • 相关阅读:
    路由器实验之配置实验、直连路由验证、静态路由
    RIP路由选择实验
    多线程编程核心技术(十五)CountDownLatch和CyclicBarrier
    maven新建项目时的Run配置
    archetypeCatalog=internal
    Archetype插件的介绍和使用
    maven POM中的source和target编译参数是什么意思
    什么是IOC?
    什么是POJO?
    @SpringBootConfiguration注解
  • 原文地址:https://www.cnblogs.com/zgf-666/p/8613367.html
Copyright © 2011-2022 走看看