Socket.IOでリアルタイム双方向通信

Socket.IOは、双方向通信を実現してくれるNode.jsのライブラリです。ここでは、簡単なプログラムを通じて双方向通信の動作確認をします。(Client側もNode.jsを利用しており、実装はTypeScriptで行っています。)

WebSocketについて

WebSocketは、双方向通信を行うためのプロトコルです。通信のたびに新しくコネクションを確立する必要がなく、HTTPに比べて軽量なヘッダなので、双方向通信を低コストで実現できます。

ws:wss: のURIスキームが定義されています。wss: はTLSで暗号化されます。

ブラウザサポート状況は以下サイトで確認できます。
https://caniuse.com/websockets

Socket.IOについて

Socket.IOは、WebSocketの実装というわけではないですが、状況に合わせて WebSocketロングポーリング など利用して双方向通信を実現してくれます。

前準備

必要パッケージをインストールします。今回、Client側もnode.jsで確認するので socket.io-client もインストールします。

npm init
npm install socket.io socket.io-client

処理は TypeScript で記述します。

npm install --save-dev typescript
npx tsc --init

動作確認1|接続

まずは、接続だけ行います。

server.ts

import http from 'http';
import socketio from 'socket.io';

const server: http.Server = http.createServer();
const io: socketio.Server = new socketio.Server(server);

io.on('connection', (socket: socketio.Socket) => console.log('connect'));

const port = 5000;
server.listen(port, () => console.log(`app listening on port ${port}`));

client.ts

import { io } from 'socket.io-client';

const port = 5000;
const socket = io(`http://localhost:${port}`);

socket.on('connect', () => console.log('connect'));

動作確認

760-nodejs-socketio_00.png

server.tsだけ起動しています。

760-nodejs-socketio_01.png

client.tsも起動して接続されました。

動作確認2|Server - Client間で通信
( emit )

双方間通信を確認します。

server.ts

import http from 'http';
import socketio from 'socket.io';

const server: http.Server = http.createServer();
const io: socketio.Server = new socketio.Server(server);

io.on('connection', (socket: socketio.Socket) => {
  console.log('connect');

  let counter = 0;

  // Clientからメッセージを受信
  socket.on('yyy', (data: { message: string }) => {
    console.log(`type: ${typeof data}   data: ${data.message}`);
  });

  // Clientにメッセージを送信
  setInterval(() => {
    socket.emit('xxx', { message: `server message ${counter++}` });
  }, 1000);
});

const port = 5000;
server.listen(port, () => {
  console.log(`app listening on port ${port}`);
});

client.ts

import { io } from 'socket.io-client';

const port = 5000;
const socket = io(`http://localhost:${port}`);

socket.on('connect', () => {
  console.log('connect');
});

// Serverからメッセージを受信
socket.on('xxx', (data: { message: string }) => {
  console.log(`type: ${typeof data}   data: ${data.message}`);
});

// Serverにメッセージを送信
let counter = 0;
setInterval(() => {
  socket.emit('yyy', { message: `client message ${counter++}` });
}, 1000);

補足

760-nodejs-socketio_10.png

serverからclientに xxx eventを通じてメッセージを送信しています。
clientからserverに yyy eventを通じてメッセージを送信しています。

動作確認

760-nodejs-socketio_11.png

双方向の通信を確認できました。

動作確認2|任意の範囲内で通信
( room )

roomという機能が提供されており、roomにjoinしている範囲内で通信できます。

Rooms | Socket.IO

server.ts

import http from 'http';
import socketio from 'socket.io';

const server: http.Server = http.createServer();
const io: socketio.Server = new socketio.Server(server);

io.on('connection', (socket: socketio.Socket) => {
  const socketId = socket.id;
  console.log(`[connect] socketId: ${socketId}`);

  let clientId = '';
  let roomId = '';
  let counter = 0;

  // Clientからのメッセージを受信
  socket.on('join_to_room', (data: { clientId: string; roomId: string }) => {
    roomId = data.roomId;
    clientId = data.clientId;
    socket.join(roomId);
    console.log(
      `[join to room] socketId: ${socketId} clientId: ${clientId} roomId: ${roomId}`,
    );
  });

  // Clientにメッセージを送信
  setInterval(() => {
    socket.to(roomId).emit('server_to_client', {
      message: {
        socketId,
        clientId,
        roomId,
        counter: counter++,
      },
    });
  }, 1000);
});

const port = 5000;
server.listen(port, () => {
  console.log(`app listening on port ${port}`);
});

client.ts

実行時、引数で clientId roomId を指定できるようにしています。

import { io } from 'socket.io-client';

const port = 5000;
const socket = io(`http://localhost:${port}`);

const clientId = process.argv[2];
const roomId = process.argv[3];
console.log(`clientId: ${clientId}  roomId: ${roomId}`);

socket.on('connect', () => {
  console.log('connect');
});

// Serverからメッセージを受信
socket.on('server_to_client', (data: { message: object }) => {
  console.log(JSON.stringify(data.message));
});

// Serverにメッセージを送信
socket.emit('join_to_room', { clientId, roomId });

補足

760-nodejs-socketio_20.png

serverは、clientから join_to_room eventを通じてメッセージを受信したタイミングで roomjoin します。
serverは、room を指定したうえで、 server_to_client eventを通じてclientにメッセージを送信しています。

動作確認

1. server.tsを起動

760-nodejs-socketio_21.png

2. client.tsを起動(ClientA)

760-nodejs-socketio_22.png

3. client.tsを起動(ClientB)

ClientAとは異なるroomIdを指定して起動します。

760-nodejs-socketio_23.png

roomId が異なるのでメッセージは表示されません。

4. client.tsを起動(ClientC)

ClientAとは同じ roomId を指定して起動します。

760-nodejs-socketio_24.png

ClientAとClientCで roomId が同じなので、ClientAの画面にはClientCのメッセージが表示され、ClientCの画面にはClientAのメッセージが表示されています。

参考

WebSocket関連

Socket.IO関連

【エンジニア向け】仕事を見つける方法

転職する

転職エージェントを活用する

転職サイトの場合、自身でサイト上から企業を探す必要があります。 一方「レバテックキャリア」 などの転職エージェントの場合、エージェントが企業を紹介してくれます。エージェントが間に入ることにより、日程調整や、条件交渉などもサポートしてくれます。

転職ドラフトを活用する

転職ドラフト」は、 企業がITエンジニアをドラフトという形で指名するサービスです。年収が最初に提示されるなどのメリットがあります。 ただ、初回登録時にレジュメ作成が必要で、すでにエンジニア経験が豊富にあるエンジニア向けのサービスかと思います。 レジュメ作成が手間ですが、自身のキャリアを見直す機会になり、他の仕事探しにも役立つはずです。

エンジニア転職保証のあるスクールを活用する

ある程度、開発経験のあるかたであれば、独学で必要なスキルを身につけることができるはずです。ただ、別業種からエンジニアに転職したい場合など、1から独学で学ぶのはハードルが高いです。そういった方は、スクールの活用を検討しても良いと思います。 「TechAcademy」は、エンジニア転職保証コースを提供しています。給付金制度の対象講座として認定されているため、金銭面の負担も抑えることができます。

フリーランスとして活動する

レバテックフリーランス」「ITプロパートナーズ」「ギークスジョブ」は、フリーランスエージェントサービスです。 エージェントによって、支払いサイトなど細かい違いはありますが、まずは良い案件を見つけることが重要です。 登録自体は無料なので、複数エージェントに登録して、より多くの案件を紹介してもらうのがおすすめです。

logo
わくわくBank.
技術系の記事を中心に、役に立つと思ったこと、整理したい情報などを掲載しています。