├── 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 |
--------------------------------------------------------------------------------