├── README.md ├── client ├── .gitignore ├── package-lock.json ├── package.json ├── public │ └── index.html └── src │ ├── index.css │ └── index.js └── server ├── .gitignore ├── index.js ├── package-lock.json └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # WebSocket-Chat-App -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webSocketClient", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "react-scripts start", 8 | "build": "react-scripts build", 9 | "test": "react-scripts test", 10 | "eject": "react-scripts eject", 11 | "buildUi": "rm -rf ../server/build && npm run build --prod && cp -r build ../server" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "antd": "^4.1.2", 18 | "react": "^16.13.1", 19 | "react-dom": "^16.13.1", 20 | "react-scripts": "^3.4.1", 21 | "websocket": "^1.0.31" 22 | }, 23 | "browserslist": { 24 | "production": [ 25 | ">0.2%", 26 | "not dead", 27 | "not op_mini all" 28 | ], 29 | "development": [ 30 | "last 1 chrome version", 31 | "last 1 firefox version", 32 | "last 1 safari version" 33 | ] 34 | }, 35 | "devDependencies": { 36 | "playwright": "1.3.0", 37 | "qawolf": "1.3.6" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Socket chat 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #bae7ff; 3 | } 4 | 5 | .main { 6 | height: 100vh; 7 | width: 100vw; 8 | background-color: #bae7ff; 9 | } 10 | 11 | .title { 12 | text-align: center; 13 | width: 100%; 14 | padding: 2%; 15 | background-color: #91d5ff; 16 | color: #efefef; 17 | } 18 | 19 | .bottom { 20 | position: fixed; 21 | width: 100%; 22 | left: 0; 23 | bottom: 0; 24 | } -------------------------------------------------------------------------------- /client/src/index.js: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom'; 2 | import React, { Component } from 'react'; 3 | import { w3cwebsocket as W3CWebSocket } from "websocket"; 4 | import { Card, Avatar, Input, Typography } from 'antd'; 5 | import 'antd/dist/antd.css'; 6 | import './index.css' 7 | 8 | const { Search } = Input; 9 | const { Text } = Typography; 10 | const { Meta } = Card; 11 | 12 | const client = new W3CWebSocket('ws://127.0.0.1:8004'); 13 | 14 | export default class App extends Component { 15 | 16 | state ={ 17 | userName: '', 18 | isLoggedIn: false, 19 | messages: [] 20 | } 21 | 22 | onButtonClicked = (value) => { 23 | client.send(JSON.stringify({ 24 | type: "message", 25 | msg: value, 26 | user: this.state.userName 27 | })); 28 | this.setState({ searchVal: '' }) 29 | } 30 | componentDidMount() { 31 | client.onopen = () => { 32 | console.log('WebSocket Client Connected'); 33 | }; 34 | client.onmessage = (message) => { 35 | const dataFromServer = JSON.parse(message.data); 36 | console.log('got reply! ', dataFromServer); 37 | if (dataFromServer.type === "message") { 38 | this.setState((state) => 39 | ({ 40 | messages: [...state.messages, 41 | { 42 | msg: dataFromServer.msg, 43 | user: dataFromServer.user 44 | }] 45 | }) 46 | ); 47 | } 48 | }; 49 | } 50 | render() { 51 | return ( 52 |
53 | {this.state.isLoggedIn ? 54 |
55 |
56 | Websocket Chat: {this.state.userName} 57 |
58 |
59 | {this.state.messages.map(message => 60 | 61 | {message.user[0].toUpperCase()} 64 | } 65 | title={message.user+":"} 66 | description={message.msg} 67 | /> 68 | 69 | )} 70 |
71 |
72 | this.setState({ searchVal: e.target.value })} 78 | onSearch={value => this.onButtonClicked(value)} 79 | /> 80 |
81 |
82 | : 83 |
84 | this.setState({ isLoggedIn: true, userName: value })} 89 | /> 90 |
91 | } 92 |
93 | ) 94 | } 95 | } 96 | 97 | ReactDOM.render(, document.getElementById('root')); -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | const webSocketsServerPort = 8004; 2 | const webSocketServer = require('websocket').server; 3 | const http = require('http'); 4 | 5 | // Spinning the http server and the websocket server. 6 | const server = http.createServer(); 7 | server.listen(webSocketsServerPort); 8 | console.log(`listening on port ${webSocketsServerPort}`); 9 | 10 | 11 | const wsServer = new webSocketServer({ 12 | httpServer: server 13 | }); 14 | 15 | const clients = {}; 16 | 17 | // This code generates unique userid for everyuser. 18 | const getUniqueID = () => { 19 | const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); 20 | return s4() + s4() + '-' + s4(); 21 | }; 22 | 23 | wsServer.on('request', function (request) { 24 | var userID = getUniqueID(); 25 | console.log((new Date()) + ' Recieved a new connection from origin ' + request.origin + '.'); 26 | 27 | // You can rewrite this part of the code to accept only the requests from allowed origin 28 | const connection = request.accept(null, request.origin); 29 | clients[userID] = connection; 30 | console.log('connected: ' + userID + ' in ' + Object.getOwnPropertyNames(clients)); 31 | 32 | connection.on('message', function (message) { 33 | if (message.type === 'utf8') { 34 | console.log('Received Message: ', message.utf8Data); 35 | 36 | // broadcasting message to all connected clients 37 | for (key in clients) { 38 | clients[key].sendUTF(message.utf8Data); 39 | // console.log('sent Message to: ', clients[key]); 40 | } 41 | console.log(`send messages to ${Object.keys(clients).length} clients`); 42 | } 43 | }) 44 | }); -------------------------------------------------------------------------------- /server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "bufferutil": { 8 | "version": "4.0.2", 9 | "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.2.tgz", 10 | "integrity": "sha512-AtnG3W6M8B2n4xDQ5R+70EXvOpnXsFYg/AK2yTZd+HQ/oxAdz+GI+DvjmhBw3L0ole+LJ0ngqY4JMbDzkfNzhA==", 11 | "requires": { 12 | "node-gyp-build": "^4.2.0" 13 | } 14 | }, 15 | "d": { 16 | "version": "1.0.1", 17 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 18 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 19 | "requires": { 20 | "es5-ext": "^0.10.50", 21 | "type": "^1.0.1" 22 | } 23 | }, 24 | "debug": { 25 | "version": "2.6.9", 26 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 27 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 28 | "requires": { 29 | "ms": "2.0.0" 30 | } 31 | }, 32 | "es5-ext": { 33 | "version": "0.10.53", 34 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", 35 | "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", 36 | "requires": { 37 | "es6-iterator": "~2.0.3", 38 | "es6-symbol": "~3.1.3", 39 | "next-tick": "~1.0.0" 40 | } 41 | }, 42 | "es6-iterator": { 43 | "version": "2.0.3", 44 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 45 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", 46 | "requires": { 47 | "d": "1", 48 | "es5-ext": "^0.10.35", 49 | "es6-symbol": "^3.1.1" 50 | } 51 | }, 52 | "es6-symbol": { 53 | "version": "3.1.3", 54 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 55 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 56 | "requires": { 57 | "d": "^1.0.1", 58 | "ext": "^1.1.2" 59 | } 60 | }, 61 | "ext": { 62 | "version": "1.4.0", 63 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", 64 | "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", 65 | "requires": { 66 | "type": "^2.0.0" 67 | }, 68 | "dependencies": { 69 | "type": { 70 | "version": "2.1.0", 71 | "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", 72 | "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" 73 | } 74 | } 75 | }, 76 | "http": { 77 | "version": "0.0.1-security", 78 | "resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz", 79 | "integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==" 80 | }, 81 | "is-typedarray": { 82 | "version": "1.0.0", 83 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 84 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 85 | }, 86 | "ms": { 87 | "version": "2.0.0", 88 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 89 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 90 | }, 91 | "next-tick": { 92 | "version": "1.0.0", 93 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", 94 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" 95 | }, 96 | "node-gyp-build": { 97 | "version": "4.2.3", 98 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", 99 | "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" 100 | }, 101 | "type": { 102 | "version": "1.2.0", 103 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 104 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" 105 | }, 106 | "typedarray-to-buffer": { 107 | "version": "3.1.5", 108 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 109 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 110 | "requires": { 111 | "is-typedarray": "^1.0.0" 112 | } 113 | }, 114 | "utf-8-validate": { 115 | "version": "5.0.3", 116 | "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.3.tgz", 117 | "integrity": "sha512-jtJM6fpGv8C1SoH4PtG22pGto6x+Y8uPprW0tw3//gGFhDDTiuksgradgFN6yRayDP4SyZZa6ZMGHLIa17+M8A==", 118 | "requires": { 119 | "node-gyp-build": "^4.2.0" 120 | } 121 | }, 122 | "websocket": { 123 | "version": "1.0.33", 124 | "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.33.tgz", 125 | "integrity": "sha512-XwNqM2rN5eh3G2CUQE3OHZj+0xfdH42+OFK6LdC2yqiC0YU8e5UK0nYre220T0IyyN031V/XOvtHvXozvJYFWA==", 126 | "requires": { 127 | "bufferutil": "^4.0.1", 128 | "debug": "^2.2.0", 129 | "es5-ext": "^0.10.50", 130 | "typedarray-to-buffer": "^3.1.5", 131 | "utf-8-validate": "^5.0.2", 132 | "yaeti": "^0.0.6" 133 | } 134 | }, 135 | "yaeti": { 136 | "version": "0.0.6", 137 | "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", 138 | "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "Using websocket to create a server communication app", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "http": "0.0.1-security", 15 | "websocket": "^1.0.31" 16 | } 17 | } 18 | --------------------------------------------------------------------------------