如何通过服务器端网页的JavaScript调用客户端C#/VB程序函数并实现本地串口数据交互?
Absolutely—your current tech stack (C#/VB for the local EXE + remote JavaScript) is fully capable of building this application. The CORS error you're facing is a standard browser security restriction, and we can fix it with a few tweaks to your VB HttpListener code. Let's break down the steps to get this working:
1. Fix the CORS Error
The CORS issue happens because your remote JavaScript is making requests from a different domain than localhost:9091, and browsers block cross-origin requests by default unless the server explicitly allows them. To fix this, add CORS response headers to your VB HttpListener handler.
Here's the modified version of your ProcessRequests method with CORS support:
Private Sub ProcessRequests(ByVal prefixes() As String) If Not System.Net.HttpListener.IsSupported Then Console.WriteLine( _ "Windows XP SP2, Server 2003, or higher is required to " & _ "use the HttpListener class.") Exit Sub End If If prefixes Is Nothing OrElse prefixes.Length = 0 Then Throw New ArgumentException("prefixes") End If Dim listener As System.Net.HttpListener = New System.Net.HttpListener() For Each s As String In prefixes listener.Prefixes.Add(s) Next Try listener.Start() Console.WriteLine("Listening...") Dim numRequestsToBeHandled As Integer = 10 ' Adjust this or make it infinite for long-running use For i As Integer = 0 To numRequestsToBeHandled Dim response As HttpListenerResponse = Nothing Try Dim context As HttpListenerContext = listener.GetContext() response = context.Response ' --- Add CORS Headers --- ' Replace with your actual remote server domain for better security (avoid using *) response.Headers.Add("Access-Control-Allow-Origin", "https://your-remote-server.com") response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS") response.Headers.Add("Access-Control-Allow-Headers", "Content-Type") ' Handle OPTIONS preflight requests (required for most cross-origin requests) If context.Request.HttpMethod = "OPTIONS" Then response.StatusCode = 200 response.Close() Continue For End If ' --- Process Query String (your existing logic) --- Dim IncMessage As NameValueCollection = context.Request.QueryString For Each key As String In IncMessage.Keys Dim Values() As String = IncMessage.GetValues(key) For Each value In Values MsgBox($"{key} equals {value}") Next Next ' --- Example: Return a success response --- Dim responseString As String = "Request processed successfully" Dim buffer As Byte() = System.Text.Encoding.UTF8.GetBytes(responseString) response.ContentLength64 = buffer.Length response.OutputStream.Write(buffer, 0, buffer.Length) Catch ex As HttpListenerException Console.WriteLine(ex.Message) Finally response?.Close() End Try Next Catch ex As HttpListenerException Console.WriteLine(ex.Message) Finally listener.Close() Console.WriteLine("Done Listening...") End Try End Sub
2. Integrate Serial Port Logic
Next, replace the MsgBox logic with code that connects to the serial port, reads data, and returns it to the web page. Add this serial port reading function to your module:
Private Function ReadSerialPortData(comPort As String, baudRate As Integer) As String Dim serialPort As New System.IO.Ports.SerialPort(comPort, baudRate) Try serialPort.Open() ' Adjust this to match your device's data format (ReadLine, ReadExisting, etc.) Dim serialData As String = serialPort.ReadLine() Return serialData Catch ex As Exception Return $"Error reading serial port: {ex.Message}" Finally If serialPort.IsOpen Then serialPort.Close() End If End Try End Function
Then modify your request handler to trigger this function when a specific endpoint is called (e.g., /read-serial):
' Inside the Try block after handling CORS If context.Request.HttpMethod = "GET" AndAlso context.Request.RawUrl.StartsWith("/read-serial") Then ' Get serial port parameters from query string (or hardcode if fixed) Dim comPort As String = If(context.Request.QueryString("comPort"), "COM3") Dim baudRate As Integer = If(Integer.TryParse(context.Request.QueryString("baudRate"), baudRate), baudRate, 9600) Dim serialData As String = ReadSerialPortData(comPort, baudRate) Dim buffer As Byte() = System.Text.Encoding.UTF8.GetBytes(serialData) response.ContentLength64 = buffer.Length response.ContentType = "text/plain" response.OutputStream.Write(buffer, 0, buffer.Length) End If
3. Key Optimizations & Security Tips
- Restrict CORS Origins: Never use
"*"in production—replace it with your exact remote server domain (e.g.,https://your-app-domain.com) to prevent unauthorized sites from accessing your local service. - Add Authentication: Include a simple token or API key in your requests (e.g.,
?token=your-secret-key) and validate it in your VB code before executing serial port operations. - Use WebSockets for Real-Time Data: If you need continuous serial data updates, replace HTTP requests with WebSockets.
HttpListenersupports WebSockets (on Windows 8+), allowing your local EXE to push data to the web page in real-time without polling. - Make the EXE a Windows Service: Convert your VB application into a Windows Service so it runs automatically in the background, no need for users to manually launch the EXE.
Final Verdict
Your existing skills in C#/VB and JavaScript are more than enough to build this solution. Start by fixing the CORS issue, then integrate the serial port logic, and gradually add optimizations for security and reliability.
内容的提问来源于stack exchange,提问作者HoTsOuRcE

