zoukankan      html  css  js  c++  java
  • socket 代码实例

    1. TCP SOCKET

    客户端:

    #!/usr/bin/env python
    # -*-coding:utf-8 -*-
    import socket
    HOST = 'localhost'
    PORT = 50001
    
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect((HOST, PORT))
    
    while True:
        msg = input('>>:').strip()
        if len(msg) == 0: continue  # 如果输入为空,跳过此次循环进行下一次。 TCP 协议不可以发空
        client.send(msg.encode()) # 发送输入的数据,必须为bytes格式
        data = client.recv(1024)
        print('recived:', data.decode())  # 收到服务器传过来的数据,要decode 一下
    

    服务端:

    #!/usr/bin/env python
    # -*-coding:utf-8 -*-
    import socket
    HOST = ''
    PORT = 50001
    
    gd_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    gd_server.bind((HOST, PORT))
    
    gd_server.listen(1)  # 开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝
    conn, addr = gd_server.accept()  # 阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象
    print(conn, addr)
    
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)  # 接收1024个字节
            print("server recv:", conn.getpeername(), data.decode())
            if not data: break  # 收不到数据,就break
            conn.sendall(data)  # 把收到的数据再全部返回给客户端
    

    先启动服务端,再启动客户端

    # 客户端:
    >>:hello
    recived: hello
    >>:茉莉
    recived: 茉莉
    >>:
    
    # 服务端
    <socket.socket fd=268, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 50001), raddr=('127.0.0.1', 51711)> ('127.0.0.1', 51711)
    Connected by ('127.0.0.1', 51711)
    server recv: ('127.0.0.1', 51711) hello
    server recv: ('127.0.0.1', 51711) 茉莉
    


    简单版聊天软件

    客户端代码同上

    服务端代码:

    #!/usr/bin/env python
    # -*-coding:utf-8 -*-
    import socket
    HOST = ''
    PORT = 50002
    
    gd_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    gd_server.bind((HOST, PORT))
    
    gd_server.listen(1)  # 开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝
    conn, addr = gd_server.accept()  # 阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象
    print(conn, addr)
    
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)  # 接收1024个字节
            print("recv from client:", conn.getpeername(), data.decode())
            if not data: break  # 收不到数据,就break
    
            response = input(">>>").strip()
            conn.send(response.encode())
            print("send to client:",response)
    

    运行结果

    如果想要服务端一直在运行中的状体,即服务端不会因为客户端断而链接断开,可以在最外层再加一个 while True 循环即可:


    s.send()
    # 发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。 所以,send() 执行一次,可能不会把所有数据都发送完毕。
    
    s.sendall()
    
    # 完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 
    

    如果遇到这个问题:

    解决方法:

    sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #一行代码搞定,写在bind之前
    sock_server.bind((HOST, PORT))
    


    2. UDP SOCKET

    udp 不需要经过3次握手和4次挥手,不需要提前建立连接,直接发数据就行。

    客户端:

    #!/usr/bin/env python
    # -*-coding:utf-8 -*-
    import socket
    ip_port = ('127.0.0.1',9000)
    BUFSIZE = 1024
    udp_server_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # socket.SOCK_DGRAM
    
    while True:
        msg=input('>>: ').strip()
        if not msg:continue
        udp_server_client.sendto(msg.encode('utf-8'),ip_port)  # sendto
    
        back_msg,addr = udp_server_client.recvfrom(BUFSIZE)
        print(back_msg.decode('utf-8'),addr)
    

    服务端:

    import socket
    ip_port=('127.0.0.1', 9000)
    BUFSIZE=1024
    
    udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  # udp类型
    udp_server_client.bind(ip_port)
    
    while True:
        msg,addr=udp_server_client.recvfrom(BUFSIZE)  # recvfrom
        print("recv ",msg,addr)
    
        udp_server_client.sendto(msg.upper(), addr)
    


    3. UDP and TCP

    tcp基于链接通信

    • 基于链接,则需要listen(backlog),指定连接池的大小
    • 基于链接,必须先运行的服务端,然后客户端发起链接请求
    • 对于mac系统:如果一端断开了链接,那另外一端的链接也跟着完蛋recv将不会阻塞,收到的是空(解决方法是:服务端在收消息后加上if判断,空消息就break掉通信循环)
    • 对于windows/linux系统:如果一端断开了链接,那另外一端的链接也跟着完蛋recv将不会阻塞,收到的是空(解决方法是:服务端通信循环内加异常处理,捕捉到异常后就break掉通讯循环)

    udp无链接

    • 无链接,因而无需listen(backlog),更加没有什么连接池之说了
    • 无链接,udp的sendinto不用管是否有一个正在运行的服务端,可以己端一个劲的发消息,只不过数据丢失
    • recvfrom收的数据小于sendinto发送的数据时,在mac和linux系统上数据直接丢失,在windows系统上发送的比接收的大直接报错
    • 只有sendinto发送数据没有recvfrom收数据,数据丢失
  • 相关阅读:
    POJ 1426 Find The Multiple(数论——中国同余定理)
    POJ 2253 Frogger(Dijkstra变形——最短路径最大权值)
    POJ 3790 最短路径问题(Dijkstra变形——最短路径双重最小权值)
    POJ 3278 Catch That Cow(模板——BFS)
    HDU 1071 The area
    HDU 1213 How Many Tables(模板——并查集)
    POJ 1611 The Suspects
    light oj 1214 Large Division
    POJ 1258 Agri-Net(Prim算法求解MST)
    POJ 2387 Til the Cows Come Home(模板——Dijkstra算法)
  • 原文地址:https://www.cnblogs.com/friday69/p/9473350.html
Copyright © 2011-2022 走看看