草庐IT

Javascript Node.js 和 Socket.IO 广播服务器

coder 2023-09-18 原文

我只需要一个简单的例子来解释如何做一个 Node.JS 服务器。

基本上 Node.JS 将有 2 个服务器运行: - 一个粗糙的 TCP 服务器和 - 一个 Socket.IO 服务器 目标是将数据从 TCP Client 转发到对其感兴趣的各种 Socket.IO 客户端

这样做的原因是为了更容易与其他语言进行通信(我将让一个 java 服务器在 tcp 套接字中发送消息,因为我找不到更好的方法来做到这一点 - 所有可用的 java 库( socket.io 服务器和用 java 实现的客户端)是错误的)因为几乎每种语言都有套接字 api。

TCP 客户端将在连接后立即发送一个字符串,Node.JS 服务器将使用它创建一个命名空间并为其提供数据,因此 Socket.IO 客户端必须能够接收服务器将从 TCP 转发的数据客户。

步骤:

  • 监听 TCP 连接

  • 在一个新的 TCP 连接上从客户端接收一个字符串

  • 创建一个 Socket.IO 服务器,其 namespace 命名为从 tcp 客户端提供的字符串

  • 开始从 TCP 客户端接收数据并将其广播到连接到此套接字打开时创建的命名空间的所有 Socket.IO 客户端

这必须以各种 TCP 客户端和 Socket.IO 客户端可以通信的方式进行

我找不到如何以有效的方式执行此操作,如果有人可以提供一个简单的示例,我相信它会对很多人有所帮助(因为 Node.JS 和 Socket.IO 缺乏文档)并且这很容易为已经知道该主题的人制作。

谢谢。


更新:

我做到了:

node.js 代码:

var javaPort = 8080;
var sIOPort = 8081;
var javaServer = require('net').createServer();
var browserServer = require('socket.io').listen(sIOPort);

console.log('Socket.IO version: ' + require('socket.io').version);

javaServer.on('listening', function () {
    console.log('Server is listening on ' + javaPort);
});

javaServer.on('error', function (e) {
    console.log('Server error: ' + e.code);
});

javaServer.on('close', function () {
    console.log('Server closed');
});

javaServer.on('connection', function (javaSocket) {
    var clientAddress = javaSocket.address().address + ':' + javaSocket.address().port;
    console.log('Java ' + clientAddress + ' connected');

    var firstDataListenner = function (data) {
        console.log('Received namespace from java: ' + data);
        javaSocket.removeListener('data', firstDataListenner);
        createNamespace(data, javaSocket);
    }

    javaSocket.on('data', firstDataListenner);

    javaSocket.on('close', function() {
        console.log('Java ' + clientAddress + ' disconnected');
    });
});

javaServer.listen(javaPort);

function createNamespace(namespaceName, javaSocket) {
    var browserConnectionListenner = function (browserSocket) {
        console.log('Browser Connected');
        var javaSocketDataListenner = function(data) {
            console.log('Data received from java socket and sent to browser: ' + data);
            browserSocket.emit('m', data + '\r\n');
        }

        var javaSocketClosedListenner = function() {
            console.log('The java socket that was providing data has been closed, removing namespace'); 
            browserSocket.disconnect();
            browserServer.of('/' + namespaceName).removeListener('connection', browserConnectionListenner);
            javaSocket.removeListener('data', javaSocketDataListenner);
            javaSocket.removeListener('close', javaSocketClosedListenner);
        }

        javaSocket.on('close', javaSocketClosedListenner);
        javaSocket.on('data', javaSocketDataListenner);

        browserSocket.on('disconnect', function () {
            console.log('Browser Disconnected');
            javaSocket.removeListener('data', javaSocketDataListenner);
            javaSocket.removeListener('close', javaSocketClosedListenner);
        });
    }

    var namespace = browserServer.of('/' + namespaceName).on('connection', browserConnectionListenner);
}

java代码:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class Client {

    public static void main(String[] args) {
        try {
            Socket nodejs = new Socket("localhost", 8080);
            sendMessage(nodejs, "testnamespace");
            Thread.sleep(100);
            int x = 0;
            while (true)
            {
                sendMessage(nodejs, x + "");
                x++;
                Thread.sleep(1000);
                System.out.println(x + " has been sent to server");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void sendMessage(Socket s, String message) throws IOException {
        s.getOutputStream().write(message.getBytes("UTF-8"));
        s.getOutputStream().flush();
    }

    public static String readMessage(Socket s) throws IOException {
        InputStream is = s.getInputStream();
        int curr = -1;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        while ((curr = is.read()) != -1) {
            if (curr == '\n') {
                break;
            }
            baos.write(curr);
        }
        return baos.toString("UTF-8");
    }
}

html代码:

<html>
    <head>
    <script src="socket.io.js"></script>
    </head>
    <body>
    <script>
        var socket = io.connect("http://localhost/testnamespace", {port: 8081});
        console.log(io.version);
        socket.on('connect', function () {
            console.log('Connected');
            });
        socket.on('m', function (msg) {
            console.log('Message received: ' + msg);
        });
        socket.on('disconnect', function () {
            console.log('Disconnected');
        });
    </script>
    </body>
</html>

工作原理:

Java 不通过 TCP 套接字连接任何 nodejs 然后发送命名空间名称,nodejs 使用该命名空间创建一个 socket.io 服务器并转发 java 套接字发送给连接到该命名空间的所有 socket.io 客户端的所有消息

如果有人看到错误或可以进行改进,请分享。

谢谢

最佳答案

我正在制作一个类似的应用程序,但我没有使用 TCP,而是在 TCP 之上使用 ZeroMQ。此代码非常简单。

在这里查看我的代码: https://github.com/EhevuTov/netPeek

做:

$:node support/msu_gen.js
$:node app.js

希望对您有所帮助。

附带说明一下,我认为我的回调函数没有正确实现。我想每次传递消息时我都会设置事件对象。如果您找到更好的方法,请提交带有修复的拉取请求。 :-)

关于Javascript Node.js 和 Socket.IO 广播服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8235911/

有关Javascript Node.js 和 Socket.IO 广播服务器的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  4. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  7. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  8. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  9. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  10. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

随机推荐