build立一个在IOS中使用node.js服务器的聊天应用程序

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

IOS上创build聊天应用程序的最佳方式是什么?

有什么办法可以在IOS中用node.js服务器创build聊天应用程序

任何人都可以给我build议吗?

感谢您的build议

因为你可以用iOS / Android和HTML使用Socket.io创build聊天应用程序!

有两种方法可以做到这一点!

i)使用Socket.io实现你自己的套接字通信(这是diffucult,因为你需要自己编写大部分的networking实现)

Socket.io将作为stream的接口,你需要连接你的iOS!

你可以参考iOS开发指南如何实现stream!

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

有一个积极的线程,也讨论这个呢!

iPhone与Objective-C套接字通信与Socket.IO

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

这个库主要完成networking部分,你只需要实现你的应用逻辑!

iOS版

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

Android的

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

先从图书馆开始,然后尝试自己的实施,这将是很好的! :))

我build议如下:

  1. 在服务器上用node.js和NOSQL数据库(在我的例子中是CouchDb)开发HTML5应用程序
  2. 不要为你的第一个操场使用socket.io,因为它的复杂性。 你必须先了解websocket。

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

我附上了工作样本(感谢Ales Smodis)。 对于示例波纹pipe工作,您需要安装2个node.js数据包:

npm install websocket npm install nano 

你需要创builddatabse并在CouchDb数据库中插入至less一个用户:

 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" width="400" height="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" width="400" height="400" 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> 

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

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

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

代码引导您join一个频道,创build一个频道并发送消息。

注意:我为Twilio工作 。 这个快速示例应用程序至less应该帮助您确定哪些function最适合您。