zoukankan      html  css  js  c++  java
  • tcp/udp

    '''
    UDP(缺乏可靠性,可以是全双工) 效率高
    缺点:
    1.不保证数据包一定会到达目的地
    2.不保证各个数据包先后顺序
    3.不保证每个数据包只到达一次
    UDP是无连接的
    UDP不提供可靠性,UDP本身不提供确认,序列号,RTT估算,超时和重传等机制
    
    TCP(是全双工的) 效率低
    优点:(可靠)
    1.客户与服务之间先建立连接,在跨该连接与那个服务器交换数据,最后终止这个连接。
    2.当TCP向另一端发送数据,要求对端返回一个确认,没有收到确认,TCP就会自动重传数据并等待更长时间(多次失败后,断开连接)
    3.TCP提供流量控制(server接受多大字节数)
    '''
    import socket
    import os
    import signal
    import select
    import queue
    
    listened = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    listened.bind(('127.0.0.1', 8000))
    
    listened.listen(5)
    
    print('start server')
    
    
    def str_echo(conn):
        while True:
            data = conn.recv(1024)
            if len(data) > 0:
                conn.send(data)
            if not data:
                print('read error')
                break
    
    
    def sig_chid(a, b):
        while True:
            try:
                pid, status = os.waitpid(-1, os.WNOHANG)
                if status == 0:
                    print('child process pid[%s][%s] is del' % (pid, status))
                return
            except:
                print('...')
                break
    
    
    signal.signal(signal.SIGCHLD, sig_chid)
    
    while True:
        try:
            connfd, addr = listened.accept()
            print(addr)
            if (os.fork() == 0):
                listened.close()
                str_echo(connfd)
                exit(0)
    
            connfd.close()
        except KeyboardInterrupt:
            listened.close()
            print('close server')
            break
    
    #
    # # yong lai chu li xiaoxi
    # outputs = []
    # # neihe jiance bingfa lianjie
    # inputs = [listened]
    # # cun fang client : MSG_QUEUE
    # msg_dic = {}
    #
    # # select
    # while True:d
    #     reads, writes, execs = select.select(inputs, outputs, inputs)
    #     print(reads, writes, execs)
    #     # readable
    #     for r in reads:
    #         print('rrr', r)
    #         if r is listened:
    #             client, addr = r.accept()
    #             print(client, addr)
    #             inputs.append(client)
    #             msg_dic[client] = queue.Queue()
    #         else:
    #             data = r.recv(1024)
    #             print('data:', data)
    #             if data:
    #                 msg_dic[r].put(data)
    #                 outputs.append(r)
    #             else:
    #                 #remove  client
    #                 inputs.remove(r)
    #                 del msg_dic[r]
    #
    #     for w in writes:
    #         print('www', w)
    #         data = msg_dic[w].get()
    #         w.send(data)
    #         #
    #         outputs.remove(w)
    server
    import socket
    import os
    import signal
    
    def create_a_client():
        sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sockfd.connect(('127.0.0.1', 8000))
    
        return sockfd
    
    
    # version:1
    def str_cli(sock):
        stdineof = 0
        while True:
            try:
                if stdineof:
                    # jing li le EOF shoudong guanbi client
                    print('close client nomal')
                    exit(0)
                msg = input('>>>')
                sock.send(msg.encode('utf8'))
                recv_msg = sock.recv(1024)
                print(stdineof, recv_msg)
                if recv_msg:
                    print('recieve msg : %s' % recv_msg)
                else:
                    print('server is closed')
            except EOFError:
                # client close
                stdineof = 1
                sock.shutdown(socket.SHUT_WR)
                continue
    
    
    # nomal
    # sockfds = [create_a_client()]
    # # create 5 clients
    # # for i in range(5):
    # #     sockfds.append(create_a_client())
    #
    # try:
    #     str_cli(sockfds[0])
    # except BrokenPipeError:
    #     print('server is closed')
    #     exit(0)
    
    
    # selet solve
    # 1.zhongzhi  input
    # 2.piliang shuru wenti
    import sys
    import select
    import queue
    
    # readable
    inputs = [create_a_client(), sys.stdin]
    # writeable
    outpus = []
    
    
    # version:2
    def select_str_cli(rl: list, sockfd: socket.socket):
        stdineof = 0
        while True:
            reads, writes, execs = select.select(rl, [], [])
            print(reads, writes)
            for r in reads:
                if r is sys.stdin:
                    # biao zhun shu ru
                    n = sys.stdin.readline()
    
                    if n == '':
                        print('EOF signal')
                        # EOF
                        # shutdowm
                        stdineof = 1
                        sockfd.shutdown(socket.SHUT_WR)
                        continue
                    else:
                        # stdin jiaru dao ke xie
                        sockfd.send(n.encode('utf8'))
                if r is sockfd:
                    # sockfd shuju kedu
                    # sock readable
                    msg = r.recv(1024)
                    if not msg:
                        if stdineof == 1:
                            return
                        else:
                            print('serve is preclosed')
                            return
    
                    print('recv from server :%s' % msg)
    
    
    # version:3
    def fork_str_cli(sockfd:socket.socket):
        if os.fork() == 0:
            # son process
            while True:
                data = sockfd.recv(1024)
                if data:
                    print()
                    print('from server :::%s' % data)
                else:
                    break
    
            os.kill(os.getpid(),signal.SIGTERM)
            exit(0)
    
        while True:
            try:
                msg = input('>>>')
                print('sys stdin :%s' % msg)
                sockfd.send(msg.encode('utf8'))
            except EOFError:
                print('EOF')
                break
    
        sockfd.shutdown(socket.SHUT_WR)#EOF FIN
    
        return
    
    # fork_str_cli(inputs[0])
    # select_str_cli(inputs, inputs[0])
    
    
    
    exit(0)
    client

     select  解决客户端主动接受  服务区FIN信号

    以下特殊情况需要注意:

    ### TCP 客户端关闭,服务端关闭(参考Unix网络编程)
    
    
    
    #### 1.tcp客户端正常关闭
    
    ```
    当client主动发送完数据,主动键入EOF字符(*nix: Ctrl-D, Windows: Ctrl-Z+Return/Enter)
    
    1.client进程exit(0) 会主动向server发送FIN,服务器TCP会主动回一个ACK,此时关闭了tcp连接终止的前半部分。此时,服务器SOCKET处于CLOSE_WAIT状态,客户端SOCKET处于FIN_WAIT2状态。
    
    2.当服务器TCP接收到FIN时,服务器子进程阻塞与read调用,read调用返回0(即空字符串),此时返回服务器的子进程函数,服务器子进程调用exit终止。就是会触发TCP连接终止的后半部分,服务器TCP发送FIN到客户TCP,客户TCP回一个ACK给服务器TCP。至此客户端TCP处于TIME_WAIT状态。
    ```
    
    
    
    #### 2.服务器进程终止
    
    ```
    1.找到服务TCP对应的子进程kil,此时子进程所有打开的描述符都被关闭。导致服务TCP会向客户TCP发送FIN,客户TCP回一个ACK给服务TCP,此时服务TCP到客户TCP的连接终止。服务TCP处于FIN_WAIT2,客户TCP处于CLOSE_WAIT。
    
    2.此时客户端阻塞在input,此时客户端是可以向服务端send的,但是由于服务端--》客户端的连接关闭,不能send,
    于是服务器响应了一个RST给客户端,客户端recv到一个''数据。
            即客户并没有立即去 关闭到服务端的连接。
    ```
    
    #### 3.服务器主机崩溃
    
    #### 4.服务器主机崩溃后重启
    
    #### 5.服务器主机关机
  • 相关阅读:
    CocoaPods的安装和使用
    HTTP协议(一)
    iOS常用设计模式之观察者模式
    git使用方法
    关于网络开发中XML的使用
    观察者模式的具体应用——通知(notification)机制和KVO(KeyValueObserving)机制
    HTTP协议(二)之HTTP请求
    iOS常用设计模式之委托模式
    x ^y mod m
    Problem A: 速算24点
  • 原文地址:https://www.cnblogs.com/liuer-mihou/p/13627907.html
Copyright © 2011-2022 走看看