资讯专栏INFORMATION COLUMN

Python socket服务器端、客户端传送信息

Eidesen / 541人阅读

摘要:服务器端先启动后,循环等待客户端访问。使用时,要使用网络协议搜索主机也可以使用和本地非网络的套接字,但是很明显此时并没有使用使用方式时,要使用基于流套接字创建套接字,必须使用作为套接字类型。

问题

windows环境主机A上想每隔15分钟获取远程Linux主机B上定时监控的logFile文件,但通过在A主机上:telnet B"ip port (例:telnet 158.123.12.1 21)查看远程主机没开放2122端口,好像不能使用ftp或者sftp来获取(应该是不可以吧)。想自己写个简单服务器实现:
1、服务器端能够正确读取logFile内容
2、客户端访问时,服务器端能够返回logFile的内容
2、客户端能够正确获取logFile内容并写入本地文件中

解决

使用Python的socket模块,自己新增一个可以直接访问的PORT。为了保证数据准确性,使用比较简单的方法:客户端与服务器端通过TCP方式通信。服务器端先启动后,循环等待客户端访问。由于是单个客户端每隔15分钟访问,每完成一次访问便断开连接,所以采用了单线程阻塞的方法实现的服务器端:

远程Linux主机B 服务器端代码:
    #coding=utf-8
    #!/usr/bin/python
    
    from socket import *
    
    HOST = "158.123.12.1"
    PORT = 8083
    BUFSIZE = 65535
    ADDR = (HOST, PORT)
    
    tcpSerSock = socket(AF_INET, SOCK_STREAM)
    tcpSerSock.bind(ADDR)
    tcpSerSock.listen(5)
    
    welcomeStr = "Welcome to 12.1 python socket server"
    
    def logFileRead(logFile):
        """
        Read logFile by line
        return List
        """
        logFileDealList = []
        with open(logFile, "r") as logFileContent:
            for line in logFileContent.readlines():
                logFileDealList.append(line)
        return logFileDealList
    
    if __name__ == "__main__":
        fileDir = "filePath/warningMessage.txt"
    
        while True:
            print "Enter 12.1 python socket server"
            tcpCliSock, addr = tcpSerSock.accept()
            print "Connected from : ", addr
            data = tcpCliSock.recv(BUFSIZE)
    
            if not data:
                break
            print data
            logFileContentList = logFileRead(fileDir)
            # print logFileContentList
            for fileContent in logFileContentList:
                if fileContent.find("pending") == -1:
                    continue
                tcpCliSock.send("%s" % fileContent)
            tcpCliSock.close()
    
        tcpSerSock.close()

ADDRPORTint类型,要选取不冲突的PORT,在Linux上可以通过netstat -anp | grep PORT"id 例:netstat -anp | grep 8083,查看端口号占用情况。

socket(AF_INET, SOCK_STREAM):使用HOST+PORT时,要使用AF_INET网络协议搜索主机(也可以使用 TCP 和本地[非网络的 AF_LOCAL/AF_UNIX]套接字,但是很明显此时并没有使用 IP);使用TCP方式时,要使用SOCK_STREAM基于流套接字(创建 UDP 套接字,必须使用SOCK_DGRAM作为套接字类型)。

bind(ADDR):将地址(主机名、端口号对)绑定到套接字上

listen(5):设置并启动TCP监听器,参数5是在连接被转接或拒绝之前,传入连接请求的最大数连接队列最大值。如果Client端请求超过5个,Linux中Server会延迟到连接数低于5时响应连接。未测试过,具体处理流程可以参考:TCP握手与socket通信细节。由于当前只有一个Client客户端,所以5足够使用。

def logFileRead(logFile):读取文件的function

accept():被动接受TCP客户端连接,持续等待直到连接到达(阻塞等待)

tcpCliSock.recv(BUFSIZE):接收TCP消息,BUFSIZE定义的为缓冲区大小。接收的是Client端传送过来的消息。

tcpCliSock.send("%s" % fileContent):发送TCP消息,将结果返回给Client段

tcpCliSock.close():关闭客户端连接

tcpSerSock.close():退出服务器端

执行时,可以将Server端挂载到后台不退出

本地Windows主机A 客户端代码:
    #coding=utf-8
    #!/usr/bin/python
    
    from socket import *
    
    HOST = "158.123.12.1"
    PORT = 8083
    BUFSIZE = 65535
    ADDR = (HOST, PORT)
    
    welcomeStr = "Welcome to 12.1 python socket server"
    
    def fileWrite(record, fileName):
         with open(fileName, "w") as logFile:
            for recordItem in record:
                logFile.write(recordItem)
    
    def main():
        tcpCliSock = socket(AF_INET, SOCK_STREAM)
        tcpCliSock.connect(ADDR)
        fileDir = "filePath/warnLogFile.txt"
        print "Will connect 12.1 python socket server"
        data = "hello"
        tcpCliSock.send(data)
    
        retDataAll = ""
    
        while True:
            retDataTmp = tcpCliSock.recv(BUFSIZE)
            if not retDataTmp:
                break
            if not len(retDataTmp):
                break
            print retDataTmp
            retDataAll = retDataAll + retDataTmp
        print "end "
        tcpCliSock.close()
        fileWrite(retDataAll, fileDir)
    
    if __name__ == "__main__":
        main()

ADDR = (HOST, PORT):与Server端HOSTPROT相同

def fileWrite(record, fileName):覆盖写入文件,注意如果该文件不存在会报错

tcpCliSock.send(data):发送消息给服务器端

tcpCliSock.recv(BUFSIZE):注意接收服务器端返回消息时,有可能超过BUFSIZE或者超过了MTU等限制,单次获取的记录不完整。所以使用TCP协议时,通过循环判断是否存在待接收消息,直到无消息时才断开连接

参考文章

Python核心编程(第3版)
TCP握手与socket通信细节
Python中使用socket发送HTTP请求数据接收不完整问题解决方法

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/40924.html

相关文章

  • python---网络基础(socket

    摘要:套接字有两种或者称为有两个种族分别是基于文件型的和基于网络型的。大部分网络设备的都是。不会发生黏包,用户数据报协议是无连接的,面向消息的,提供高效率服务。即面向消息的通信是有消息保护边界的。 软件开发的架构 我们了解的涉及到两个程序之间通讯的应用大致可以分为两种: 第一种是应用类:qq、微信、网盘、优酷这一类是属于需要安装的桌面应用 第二种是web类:比如百度、知乎、博客园等使用浏览器...

    Dr_Noooo 评论0 收藏0
  • python网络编程

    摘要:在任何类型的通信开始之前,网络应用程序必须创建套接字。基于文件的套接字,家族名又名基于网络的套接字,家族名在和后续的版本中,支持的套接字有,,,。中的网络编程在中主要是用模块来实现基于套接字的网络通信。 python学习记录--网络编程 1、套接字介绍 一台机器上的不同进程之间进行通信可以利用队列,管道等,但是不同机器之间的进程进行通信用队列是不行的,解决这个问题就是网络套接字。 套接...

    xuhong 评论0 收藏0
  • [译]Python 中的 Socket 编程(指南)

    摘要:当一个客户端连接时,它将返回一个新的对象,对象中有表示当前连接的和一个由主机端口号组成的连接的元组,更多关于元组值的内容可以查看地址族一节中的详情这里必须要明白我们通过调用方法拥有了一个新的对象。 博客原文: https://keelii.com/2018/09/24/socket-programming-in-python/ 说明 本书翻译自 realpython 网站上的文章教程 ...

    sushi 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<