2

我正在寻找实现向服务器发送请求并检索信息的 Excel RTD 服务器。例如,这个想法如下:

用户将键入类似 =GetDuration("US912828D804") 的内容,其中参数是 ISIN 代码,并会收到债券的期限。在后面,excel 会向 python 服务器发出请求——在不同的机器上运行——所有计算都在其中完成。

到目前为止,我已经尝试使用 Excel DNA 按照他们的示例设置 excel RTD 服务器:

using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Net.Sockets;
using System.Text;
using ExcelDna.Integration.Rtd;

namespace RTDExcel
{
    [ComVisible(true)]                   // Required since the default template puts [assembly:ComVisible(false)] in the AssemblyInfo.cs
    [ProgId(RtdExcelServer_Test.ServerProgId)]     //  If ProgId is not specified, change the XlCall.RTD call in the wrapper to use namespace + type name (the default ProgId)
    public class RtdExcelServer_Test : ExcelRtdServer
    {
        public const string ServerProgId = "Test_Server_1";
        List<Topic> _topics = new List<Topic>();
        ServerClient serverClient = new ServerClient();
        Timer timer;
        int i = 0;
        public void TimeServer()
        {
            timer = new Timer(Callback);
        }

        protected override bool ServerStart()
        {                        
            serverClient.ConnectToServer();
            TimeServer();
            return true;
        }
        protected override void ServerTerminate()
        {
            serverClient.CloseConnectionToServer();
            timer.Dispose();
            timer = null;
        }

        protected override object ConnectData(Topic topic, IList<string> topicInfo, ref bool newValues)
        {            
            _topics.Add(topic);
            timer.Change(10000, 10000);
            return serverClient.AskServer("Hello");            
        }

        protected override void DisconnectData(Topic topic)
        {
            _topics.Remove(topic);
            timer.Change(-1, -1);
        }

        private void Callback(object o)
        {            
            foreach (Topic topic in _topics)
            {
                i += 1;
                topic.UpdateValue(serverClient.AskServer("Hello"));
            }            
        }
    }
}
public class ServerClient
{
    TcpClient clientSocket = new TcpClient();
    public void ConnectToServer()
    {
        clientSocket.Connect("127.0.0.1", 8080);
    }
    public string AskServer(string request)
    {
        NetworkStream serverStream = clientSocket.GetStream();
        byte[] outStream = Encoding.ASCII.GetBytes(request);
        serverStream.Write(outStream, 0, outStream.Length);
        serverStream.Flush();

        byte[] inStream = new byte[10025];
        serverStream.Read(inStream, 0, 75);
        string response = Encoding.ASCII.GetString(inStream);
        return response;
    }
    public void CloseConnectionToServer()
    {
        clientSocket.Close();
    }

}

Phython 服务器

import socketserver as ss
import datetime
import time
import pickle

class TCPHandler(ss.BaseRequestHandler):
    def handle(self):
        # self.request is the TCP socket connected to the client
        self.data = self.request.recv(1024).decode('UTF-8')
        print(self.data)
        tmp = str(datetime.datetime.now())
        print('Sending: ' + tmp)
        print('Byte Size: ' + str(sys.getsizeof(tmp)))
        self.request.sendall(tmp.encode())


if __name__ == "__main__":
    HOST, PORT = 'localhost', 8080
    # Create the server, binding to localhost on port 9999
    server = ss.TCPServer((HOST, PORT), TCPHandler)
    # Activate the server; this will keep running until you
    print('Server is running...')
    server.serve_forever()
    # interrupt the program with Ctrl-C

这个例子的主要思想是测试系统。该函数只询问服务器当前时间,这是在每次请求时计算的。不幸的是,每次计时器回调时,excel 都会崩溃。这是正确的方法吗?


更新:

似乎问题出在python服务器上,需要一个循环来保持客户端更新:

class TCPHandler(ss.BaseRequestHandler):
def handle(self):
    closed = False
    while not closed:
        try:
            self.data = self.request.recv(1024).decode('UTF-8')
            print(self.data[0])
            if self.data[0] == 'Time':
                tmp = str(datetime.datetime.now())
                print('Sending: ' + tmp)
                print('Byte Size: ' + str(sys.getsizeof(tmp)))
                self.request.send(tmp.encode())
            if self.data[0] == 'Exit':
                closed = True
            else:
                self.request.send(str('No request.').encode())
        except (KeyboardInterrupt, SystemExit):
            raise

现在我遇到的问题是服务器没有收到来自客户端的完整消息:我没有收到“时间”或“退出”,而是只收到“T”或“E”。

4

0 回答 0