在IOS中构建一个使用node.js服务器的聊天应用程序[关闭]

Posted

技术标签:

【中文标题】在IOS中构建一个使用node.js服务器的聊天应用程序[关闭]【英文标题】:Building a chat app that uses a node.js server in IOS [closed] 【发布时间】:2014-11-07 09:01:21 【问题描述】:

我正在尝试在 socket.io 上构建一个使用 node.js 的 iPhone(本机)聊天应用程序。

ios 上创建聊天应用程序的最佳方法是什么

有没有办法在IOS中用node.js服务器创建聊天应用

谁能给我建议?

谢谢你的建议

【问题讨论】:

纯 FWIW。考虑只使用 pubnub(或者 parse.com + pubnub)。几行代码就可以搞定 @joe Blow: 可能是 parse.com + pubnub 的任何示例 嗨@btmanikandan,你在吗? 【参考方案1】:

因为您可以使用带有 iOS/androidhtml 的 Socket.io 创建聊天应用程序!

有两种方法可以做到!

i) 用Socket.io实现自己的socket通信,(这个比较难,因为大部分网络实现需要自己写!)

Socket.io 将作为流接口,您需要从 iOS 连接!

您可以参考 iOS 开发指南了解如何实现流!

https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/UsingSocketsandSocketStreams.html

也有一个活跃的线程在讨论这个问题!

iPhone Objective-C socket communication with Socket.IO

ii) 使用人们为 iOS 制作的现有库或包装器,您可以在下面找到链接!

这个库主要做了网络部分,你只需要实现你的应用逻辑!

iOS

https://github.com/pkyeck/socket.IO-objc

安卓

https://github.com/nkzawa/socket.io-client.java

最好先从库开始,然后尝试自己实现! :))

【讨论】:

github.com/shuoli84/SocketIOCocoa socketio 1.0 的快速客户端【参考方案2】:

我建议如下:

    在服务器上使用 node.js 和 NOSQL 数据库(在我的示例中为 CouchDb)开发 HTML5 应用程序 不要将 socket.io 用于您的第一个游乐场,因为它很复杂。您首先必须非常了解 websockets。

不要用预先准备好的框架和大量代码给自己带来负担。您需要一个清晰、简单的代码,以便进行以后需要的修改。您需要完全控制和理解您拥有的代码。

我附上了工作样本(感谢 Ales Smodis)。为了使下面的示例工作,您需要安装 2 个 node.js 数据包:

npm install websocket
npm install nano 

您需要创建数据库并将至少 1 个用户插入 CouchDb 数据库:

curl -X PUT http://localhost:5984/chatroom
curl -X PUT -H 'Content-Type: application/json' --data '"username":"john","password":"john"' http://localhost:5984/chatroom/john

$(document).ready(function () 

    var connection,
        username = 'Tester',
        password = 'Tester',
        historyCounter = 0,
        members = ,
        // displays
        jqLogin = $('#login'),
        jqChatroom = $('#chatroom'),
        // login display components
        jqWaiting = $('#waiting'),
        jqNickname = $('#nickname'),
        jqPassword = $('#password'),
        // chat display components
        jqHistory = $('#history'),
        jqMembers = $('#members'),
        jqLine = $('#line');

    function addLine(nick, line) 
        var jq = $('<p><span class="nick"></span><span class="line"></span></p>'),
            jqNick = jq.find('.nick'),
            jqLine = jq.find('.line'),
            i, lines;
        jqNick.text(nick ? nick + ': ' : '*** ');
        jqLine.text(line);
        jqHistory.append(jq);
        historyCounter++;
        for (lines = jqHistory.children(), i = 0; historyCounter > 100; i++, historyCounter--) 
            $(lines[i]).remove();
        
    

    function addMsg(msgObj) 
        var msgHandler = states[activeState].messageHandlers[msgObj.type] || function ()  addLine(null, 'Neveljaven paket tipa ' + msgObj.type); ;
        msgHandler(msgObj);
    

    function clearMembers() 
        var nickname;
        for (nickname in members) 
            members[nickname].remove();
            delete members[nickname];
        
        jqMembers.empty(); // just in case
    

    function addMember(nickname) 
        var jq = $('<li></li>');
        jq.text(nickname);
        jqMembers.append(jq);
        members[nickname] = jq;
    

    function removeMember(nickname) 
        if (nickname in members) 
            members[nickname].remove();
            delete members[nickname];
        
    

    function connect () 
        connection = new WebSocket('ws://127.0.0.1:8080');

        connection.onopen = function () 
            states[activeState].onopen();
        ;

        connection.onmessage = function (message) 
            try 
                addMsg(JSON.parse(message.data));
            
            catch (e) 
                addLine(null, 'Exception while handling a server message: ' + e.toString());
            
        ;

        connection.onclose = function () 
            states[activeState].onclose();
        ;
    

    function loginKeypress(event) 
        if (13 !== event.keyCode) return;
        username = jqNickname.val();
        password = jqPassword.val();
        if (!username) jqNickname[0].focus();
        else if (!password) jqPassword[0].focus();
        else 
            jqWaiting.css('display', '');
            jqNickname.unbind('keydown', loginKeypress);
            jqPassword.unbind('keydown', loginKeypress);
            connect();
        
    

    function inputKeypress(event) 
        var line;
        if (13 === event.keyCode) 
            line = jqLine.val();
            if (line.length === 0) return;
            jqLine.val('');
            connection.send(JSON.stringify( 'type': 'line', 'line': line ));
        
    

    var states = 
            'login': 
                'start': function () 
                    jqChatroom.css('display', 'none');
                    jqWaiting.css('display', 'none');
                    jqLogin.css('display', '');
                    jqNickname.val('');
                    jqPassword.val('');
                    jqNickname[0].focus();
                    activeState = 'login';
                    jqNickname.bind('keydown', loginKeypress);
                    jqPassword.bind('keydown', loginKeypress);
                ,
                'onopen': function () 
                    connection.send(JSON.stringify( 'type': 'login', 'username': username, 'password': password ));
                ,
                'messageHandlers': 
                    'state': function (msgObj) 
                        var i, history, users;
                        states.chat.start();
                        history = msgObj.history;
                        jqHistory.empty();
                        historyCounter = 0;
                        for (i = 0; i < history.length; i++) addMsg(history[i]);
                        users = msgObj.users;
                        clearMembers();
                        for (i = 0; i < users.length; i++) addMember(users[i]);
                    
                ,
                'unhandledMessage': function (msgObj) 
                    connection.close(4000, 'Unhandled message type');
                ,
                'onclose': function () 
                    states.login.start();
                
            ,

            'chat': 
                'start': function () 
                    jqLogin.css('display', 'none');
                    jqWaiting.css('display', 'none');
                    jqChatroom.css('display', '');
                    jqHistory.empty();
                    historyCounter = 0;
                    activeState = 'chat';
                    jqLine.bind('keydown', inputKeypress);
                ,
                'onopen': function () 
                    connection.close(4001, 'Connection opened while chatting');
                ,
                'messageHandlers': 
                    'line': function (msgObj) 
                        addLine(msgObj.nick, msgObj.line);
                    ,
                    'join': function (msgObj) 
                        addLine(null, 'Priklopil: ' + msgObj.nick);
                        addMember(msgObj.nick);
                    ,
                    'leave': function (msgObj) 
                        addLine(null, 'Odklopil: ' + msgObj.nick);
                        removeMember(msgObj.nick);
                    
                ,
                'unhandledMessage': function (msgObj) 
                    connection.close(4000, 'Unhandled message type');
                ,
                'onclose': function () 
                    addLine(null, 'Connection closed');
                    jqLine.unbind('keydown', inputKeypress);
                
            
        ,
        activeState = 'login';

    states.login.start();
);
// node.js code
var http = require('http'),
    url = require('url'),
    path = require('path'),
    fs = require('fs'),
    nano = require('nano')('http://localhost:5984'),
    chatroomDb = nano.use('chatroom'),
    websocket = require('websocket'),
    chatHistory = [],
    activeUsers = ;

var filesDir = path.join(process.cwd(), 'web');

var mimeTypes = 
    '.html': 'text/html',
    '.css': 'text/css',
    '.js': 'text/javascript'
;

var getContentType = function (extension) 
    var mimeType = mimeTypes[extension];
    return mimeType ? mimeType : 'application/octet-stream';
;

var server = http.createServer(function (request, response) 
    var relativePath = url.parse(request.url).pathname,
        absolutePath = path.join(filesDir, relativePath);
    var handler = function (err, stats) 
        if (stats) 
            if (stats.isDirectory()) 
                absolutePath = path.join(absolutePath, 'index.html');
                fs.stat(absolutePath, handler);
                return;
            
            if (stats.isFile()) 
                response.writeHead(200, getContentType(path.extname(absolutePath)));
                var stream = fs.createReadStream(absolutePath);
                stream.pipe(response);
                return;
            
        
        response.writeHead(404, 'Content-Type': 'text/plain');
        response.write('Not found\r\n');
        response.end();
    ;
    console.log('HTTP request for ' + relativePath);
    fs.stat(absolutePath, handler);
);
server.listen(8080, function () );

wsServer = new websocket.server(
    'httpServer': server
);

function addLine (type, nick, line) 
    var msg =  'type': type, 'nick': nick, 'line': line ,
        jsonMsg = JSON.stringify(msg),
        username;
    chatHistory.push(msg);
    while (chatHistory.length > 100) chatHistory.shift();
    for (username in activeUsers) 
        activeUsers[username].sendMessage(jsonMsg);
    


wsServer.on('request', function (request) 
    console.log('New websocket connection from ' + request.origin);
    // TODO: verify that request.origin is our web site

    var connection = request.accept(null, request.origin);

    var username = null;

    connection.on('message', function (message) 
        if (message.type !== 'utf8') 
            console.log('Refusing a non-utf8 message');
            return;
        
        console.log('Processing message: ' + message.utf8Data);
        try 
            var m = JSON.parse(message.utf8Data);
            switch (m.type) 

                case 'login':
                    chatroomDb.get(m.username, function (err, body) 
                        if (err || (body.password !== m.password)) 
                            connection.close();
                            return;
                        
                        username = m.username;
                        addLine('join', username, null);
                        activeUsers[username] = 
                            'sendMessage': function (jsonMsg) 
                                connection.sendUTF(jsonMsg);
                            
                        ;
                        var users = [], u;
                        for (u in activeUsers) users.push(u);
                        connection.sendUTF(JSON.stringify( 'type': 'state', 'history': chatHistory, 'users': users ));
                    );
                    break;

                case 'line':
                    if (!username) 
                        connection.close();
                        break;
                    
                    addLine('line', username, m.line);
                    break;
            
        
        catch (e) 
            console.log(e);
        
    );

    connection.on('close', function (connection) 
        console.log('Connection closed');
        if (username) 
            delete activeUsers[username];
            addLine('leave', username, null);
        
    );
);

console.log('Server running');
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Chatroom</title>
      <style>
        html, body 
    width: 100%;
    height: 100%;
    padding: 0;
    border: none;
    margin: 0;


#heading 
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 30px;
    margin: 0;
    padding: 0;
    line-height: 30px;
    text-align: center;
    font-size: 20px;
    background-color: green;


#outer 
    position: absolute;
    top: 30px;
    bottom: 0;
    left: 0;
    right: 0;
    margin: 20px;
    min-height: 400px;
    min-width: 400px;
    background-color: lime;


#inner 
    height: 100%;
    background-color: #ffc0cb;


#chat 
    position: absolute;
    top: 0;
    left: 0;
    right: 200px;
    bottom: 0;
    background-color: #ffd700;


#members 
    position: absolute;
    top: 0;
    right: 10px;
    width: 180px;
    bottom: 0;
    background-color: #ff00ff;
    list-style-type: none;
    padding: 10px;
    padding: 0;
    border: none;


#history 
    position: absolute;
    top: 0;
    left: 0;
    bottom: 2em;
    right: 0;
    background-color: #00ffff;
    padding: 10px;


#input 
    position: absolute;
    height: 2em;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #90ee90;
    line-height: 2em;


#line 
    width: 100%;
    margin: 0;
    border: none;
    padding: 0;


#history > p 
    margin: 2px;


.nick 
    white-space: pre;
    display: table-cell;


.line 
    display: table-cell;


#login 
    height: 100%;
    display: table;
    margin: 0 auto;

#login > .svg 
    vertical-align: middle;
    display: table-cell;

#login-wrapper1 
    display: table;
    height: 100%;
    width: 100%;

#login-wrapper2 
    display: table-cell;
    vertical-align: middle;

#login-table 
    margin: 0 auto;

#login-table .label 
    text-align: right;


#waiting 
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    opacity: 0.3;


       </style> 
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
        <script src="client.js"></script>
    </head>
    <body>
        <div id="login">
            <div class="svg">

                <svg
                    xmlns="http://www.w3.org/2000/svg"
                    xmlns:xlink="http://www.w3.org/1999/xlink"
                    viewBox="0 0 400 400"
                    
                    >
                    <defs>
                        <path id="curved-text" d="M0,0 c 50 -50 150 -50 200 0" />
                    </defs>
                    <g>
                        <text
                            transform="translate(-100,40)"
                            font-weight="bold"
                            font-variant="small-caps"
                            font-family="Arial sans-serif"
                            font-size="30"
                            fill="none"
                            stroke="orange"
                            text-anchor="middle">
                            <textPath xlink:href="#curved-text" startOffset="50%">Chatroom</textPath>
                        </text>
                        <animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="360" dur="5s" fill="remove" additive="sum" repeatCount="indefinite" />
                        <animateMotion dur="10s" repeatCount="indefinite" path="M100,200 a100,100 0 1 1 200,0 a100,100 0 1 1 -200,0" />
                    </g>
                    <foreignObject
                        x="0"
                        y="0"
                        
                        
                        style="height:400px;">

                        <div xmlns="http://www.w3.org/1999/xhtml" id="login-wrapper1">
                            <div id="login-wrapper2">
                                <table id="login-table">
                                    <tbody>
                                        <tr>
                                            <td class="label">Vzdevek:</td><td><input type="text" id="nickname" /></td>
                                        </tr>
                                        <tr>
                                            <td class="label">Geslo:</td><td><input type="password" id="password" /></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>

                    </foreignObject>
                </svg>

            </div>
        </div>

        <div id="chatroom" style="display:none;">
            <h1 id="heading">Chatroom</h1>

            <div id="outer">
                <div id="inner">
                    <div id="chat">
                        <div id="history">
                            <p><span class="nick">Matej: </span><span class="line">Hi</span></p>
                            <p><span class="nick">Borut: </span><span class="line">How are you?</span></p>
                            <p><span class="nick">Martina: </span><span class="line">Ok, thanks!</span></p>
                        </div>
                        <div id="input"><input id="line" type="text"></div>
                    </div>
                    <ul id="members">
                        <li>Matej</li>
                        <li>Borut</li>
                        <li>Martina</li>
                    </ul>
                </div>
            </div>
        </div>

        <div id="waiting" style="display:none;"></div>

    </body>
</html>

【讨论】:

【参考方案3】:

如果您正在评估选项,请查看 Twilio 的 IP 消息:

https://www.twilio.com/docs/tutorials/walkthrough/ip-chat/ios/swift#0

上面的 Swift for iOS(也适用于 Objective-C)中的教程允许您在服务器端应用程序 (yours in Node.js) 生成用户访问令牌以连接到 API 时使用本机 SDK。

代码将引导您完成加入频道、创建频道和发送消息的过程。

注意:我确实为 Twilio 工作。这个快速示例应用程序至少应该可以帮助您确定最适合您的功能。

【讨论】:

以上是关于在IOS中构建一个使用node.js服务器的聊天应用程序[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Node.js笔记-使用socket.io构建websocket聊天室

如何使用 Node JS 服务器在 Socket.io 中进行一对一聊天?

PHP Socket 服务器与 node.js:网络聊天

用于在 PHP 网站中聊天的 Node.js

node.js、socket.io 和 SSL

如何将视频(来自 getUserMedia)发送到 Node.js 服务器?