TCP编程

作者: 一只写程序的猿 | 来源:发表于2017-06-15 19:13 被阅读64次

    Socket是网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可。

    TCP和UDP的区别:

    • (TCP)传输控制协议,是一种提供可靠数据传输的通用协议。
    • (UDP)用户数据报协议,是一个面向无连接的协议。采用该协议不需要两个应用程序先建立连接。UDP协议不提供差错恢复,不能提供数据重传,因此该协议传输数据安全性差。
      以上是书面内容

    1、双方都是一种[网络传输协议]
    2、TCP需要建立连接,而UDP不需要建立连接(无连接传输)  
    3、是否建立真实连接的特性,造成了双方可靠性的差距。

    • TCP属于可靠的传输协议:因为传输前双方建立好了连接,相当于买卖双方建立好了交易合同,传输中一般不会出现意外,直到连接终止;
    • UDP属于不可靠的传输协议:UDP的所谓连接相当于一种映射,UDP单方面的认为目标地址(端口)是可用的,从而进行收发数据,而实际上目标地址(端口)未必可用,所以传输数据不可靠

    4、由于TCP需要建立真实的连接,所以需要消耗服务器的负载要大于UDP

    TCP通信模型

    tcp服务器

    完成一个tcp服务器的功能,需要的流程如下:

    1. socket创建一个套接字
    2. bind绑定ip和port
    3. listen使套接字变为可以被动链接
    4. accept等待客户端的链接
    5. recv/send接收发送数据

    客户端

    大多数连接都是可靠的TCP连接。创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器。

    import socket
    import time
    
    # socket对象
    clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    print('1......')
    
    '''
    连接服务器,
        如果连接上,继续运行
        连接不上,报错
    '''
    clientSocket.connect(('192.168.11.74',8888))
    
    print('2......')
    
    #关闭
    clientSocket.close()
    

    服务端

    import socket
    import time
    
    # 买个手机
    serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 插卡
    serverSocket.bind(('', 8888))
    # 由飞行模式到接听模式
    serverSocket.listen(10)
    
    print('1......')
    
    '''
        clientAddr:连接的客户端的信息(ip,port)
    '''
    # 等待电话打入
    newSocket, clientAddr = serverSocket.accept()
    print('2......')
    print(newSocket)
    print(clientAddr)
    
    # time.sleep(100)
    # 关
    newSocket.close()  # 关闭之后,客户端也会被关闭
    
    serverSocket.close()  # 项目运行中服务器一直运行,不会关闭
    

    tcp服务端发送和接收消息

    import socket
    import time
    
    '''
    serverSocket是用来接收新的客户端的
    以后与这个连接的客户端的收发消息就不能用serverSocket了,
    而是用返回来的新的newSocket
    '''
    
    serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    
    serverSocket.bind(('', 8888))
    serverSocket.listen(10)
    
    newSocket, clientAddr = serverSocket.accept()
    
    
    #发
    sendData = input('>>')
    newSocket.send(sendData.encode('gbk'))
    #收
    '''
        此时的recv会导致阻塞。
        一旦对应客户端断开了,不阻塞,并返回''的字符串
    '''
    recvData = newSocket.recv(1024)
    print(recvData.decode('gbk'))
    
    
    
    
    newSocket.close()
    serverSocket.close()
    

    客户端接受和发送消息

    import socket
    import time
    
    clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    clientSocket.connect(('192.168.11.66',8888))
    
    
    #发
    sendData = input('>>')
    clientSocket.send(sendData.encode('gbk'))
    #收
    recvData = clientSocket.recv(1024)
    print(recvData.decode('gbk'))
    
    clientSocket.close()
    

    tcp服务器使用多线程接受多个客户端

    import socket
    import time
    import threading
    
    
    def socketState(newSocket,clientAddr):
    
        while True:
            recvData = newSocket.recv(1024)
            recvData = recvData.decode('gbk')
            if recvData == '':
                print('客户端%s退出了...'%clientAddr[0])
                newSocket.close()
                break
            else:
                print('来自于%s:%s的消息(%s):%s'%(clientAddr[0],clientAddr[1],time.strftime('%Y-%m-%d %H:%M:%S'),recvData))
                sendData = 'echo:%s'%recvData
                newSocket.send(sendData.encode('gbk'))
    
    
    def main():
        #创建服务端socket对象
        serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        serverSocket.bind(('', 8888))
        serverSocket.listen(10)
        #循环,等待多个客户端连接
        while True:
            #等待客户端的连接,阻塞。连接后,继续运行
            newSocket, clientAddr = serverSocket.accept()
    
    
            #创建新的线程,执行与新客户端的交互
            serverThread = threading.Thread(target=socketState, args=(newSocket,clientAddr))
            serverThread.start()
            # 这里不能关闭,多线程共享数据
            #newSocket.close()
    
    
    if __name__ == '__main__':
        main()
    

    服务端使用多进程接收多个客户端

    import socket
    import time
    import multiprocessing
    
    def socketState(newSocket,clientAddr):
    
        while True:
            recvData = newSocket.recv(1024)
            recvData = recvData.decode('gbk')
            if recvData == '':
                print('客户端%s退出了...'%clientAddr[0])
                newSocket.close()
                break
            else:
                print('来自于%s:%s的消息(%s):%s'%(clientAddr[0],clientAddr[1],time.strftime('%Y-%m-%d %H:%M:%S'),recvData))
                sendData = 'echo:%s'%recvData
                newSocket.send(sendData.encode('gbk'))
    
    def main():
        #创建服务端socket对象
        serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        serverSocket.bind(('', 8888))
        serverSocket.listen(10)
        #循环,等待多个客户端连接
        while True:
            #等待客户端的连接,阻塞。连接后,继续运行
            newSocket, clientAddr = serverSocket.accept()
    
            #创建新的进程,执行与新客户端的交互
            serverProcess = multiprocessing.Process(target=socketState, args=(newSocket,clientAddr))
            serverProcess.start()
            '''
                这里要关闭。
                子进程会单独分配与父进程相同的内容,地址不同(深拷贝)
           '''
            newSocket.close()
    
    
    if __name__ == '__main__':
        main()
    

    总结:

    • 用TCP协议进行Socket编程在Python中十分简单,对于客户端,要主动连接服务器的IP和指定端口,对于服务器,要首先监听指定端口,然后,对每一个新的连接,创建一个线程或进程来处理。通常,服务器程序会无限运行下去。

    • 同一个端口,被一个Socket绑定了以后,就不能被别的Socket绑定了。

    相关文章

      网友评论

        本文标题:TCP编程

        本文链接:https://www.haomeiwen.com/subject/fcyuqxtx.html