#!/usr/bin/env python3
"""
SCTP 通信工具 - 类似 netcat 的 SCTP 版本
支持服务端和客户端模式,使用 SCTP 协议(像 TCP 一样简单)
"""

import socket
import sys
import argparse
import threading

def server_mode(port):
    """启动 SCTP 服务端,监听端口并打印接收到的消息"""
    # 创建 SCTP 套接字 (SOCK_STREAM 提供面向连接的可靠字节流)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SCTP)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('0.0.0.0', port))
    sock.listen(5)
    print(f"[Server] Listening on SCTP port {port} (using SOCK_STREAM)")

    while True:
        try:
            conn, addr = sock.accept()
            print(f"[Server] Connection from {addr}")
            # 为每个客户端启动一个线程接收数据
            thread = threading.Thread(target=handle_client, args=(conn, addr))
            thread.daemon = True
            thread.start()
        except KeyboardInterrupt:
            print("\n[Server] Shutting down")
            break
    sock.close()

def handle_client(conn, addr):
    """处理客户端连接:循环接收并打印数据"""
    try:
        while True:
            data = conn.recv(4096)
            if not data:
                break
            # 尝试解码为文本,如果失败则显示十六进制
            try:
                text = data.decode('utf-8')
                print(f"[Recv from {addr}] {text}", end='')
            except UnicodeDecodeError:
                print(f"[Recv from {addr}] (binary, {len(data)} bytes): {data.hex()}")
    except Exception as e:
        print(f"[Error] {e}")
    finally:
        conn.close()
        print(f"[Server] Connection from {addr} closed")

def client_mode(server_addr, port, message=None):
    """客户端模式:连接到服务器,发送消息后退出(或交互式发送)"""
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SCTP)
    try:
        sock.connect((server_addr, port))
        print(f"[Client] Connected to {server_addr}:{port} via SCTP")
    except Exception as e:
        print(f"[Client] Connection failed: {e}")
        sys.exit(1)

    if message:
        # 直接发送指定消息
        sock.sendall(message.encode('utf-8') if isinstance(message, str) else message)
        print(f"[Client] Sent: {message}")
    else:
        # 交互模式:逐行读取 stdin 发送,空行退出
        print("[Client] Enter messages (empty line to quit):")
        while True:
            try:
                line = input()
                if line == "":
                    break
                sock.sendall((line + "\n").encode('utf-8'))
            except EOFError:
                break
    sock.close()

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="SCTP communication tool")
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument("-s", "--server", action="store_true", help="Run as server")
    group.add_argument("-c", "--client", action="store_true", help="Run as client")
    parser.add_argument("-p", "--port", type=int, required=True, help="Port number")
    parser.add_argument("-a", "--addr", default="127.0.0.1", help="Server address (client mode)")
    parser.add_argument("-m", "--message", help="Message to send (client mode, optional)")

    args = parser.parse_args()

    if args.server:
        server_mode(args.port)
    elif args.client:
        client_mode(args.addr, args.port, args.message)
//////////////////////

python3 a.py -s -p 8081
[Server] Listening on SCTP port 8081 (using SOCK_STREAM)
[Server] Connection from ('127.0.0.1', 60323)
[Recv from ('127.0.0.1', 60323)] Hello SCTP[Server] Connection from ('127.0.0.1', 60323) closed
//////////////
 python3 a.py -c -p 8081 -a 127.0.0.1 -m "Hello SCTP"
[Client] Connected to 127.0.0.1:8081 via SCTP
[Client] Sent: Hello SCTP
/////////////

tcpdump -i lo sctp port 8081
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
11:46:46.329142 IP localhost.60056 > localhost.8081: sctp (1) [INIT] [init tag: 3337461480] [rwnd: 114688] [OS: 10] [MIS: 65535] [init TSN: 3765995269]
11:46:46.329429 IP localhost.8081 > localhost.60056: sctp (1) [INIT ACK] [init tag: 4091943181] [rwnd: 114688] [OS: 10] [MIS: 10] [init TSN: 1845260209]
11:46:46.329603 IP localhost.60056 > localhost.8081: sctp (1) [COOKIE ECHO]
11:46:46.329732 IP localhost.8081 > localhost.60056: sctp (1) [COOKIE ACK]
11:46:46.334012 IP localhost.60056 > localhost.8081: sctp (1) [DATA] (B)(E) [TSN: 3765995269] [SID: 0] [SSEQ 0] [PPID 0x0]
11:46:46.334068 IP localhost.8081 > localhost.60056: sctp (1) [SACK] [cum ack 3765995269] [a_rwnd 114678] [#gap acks 0] [#dup tsns 0]
11:46:46.334260 IP localhost.60056 > localhost.8081: sctp (1) [SHUTDOWN]
11:46:46.334297 IP localhost.8081 > localhost.60056: sctp (1) [SHUTDOWN ACK]
11:46:46.334321 IP localhost.60056 > localhost.8081: sctp (1) [SHUTDOWN COMPLETE]
^C
9 packets captured
18 packets received by filter
0 packets dropped by kernel
root@nyx:/data/pub/mytest# tcpdump -i lo sctp port 8081  -w sctp.pcap
tcpdump: listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C9 packets captured
18 packets received by filter
0 packets dropped by kernel
////////////////////////////////////////////////////

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐