diff --git a/package.json b/package.json
index 840fe5a73b..e3ce2f4d2d 100644
--- a/package.json
+++ b/package.json
@@ -92,6 +92,7 @@
 		"compression": "1.7.2",
 		"cookie": "0.3.1",
 		"cors": "2.8.4",
+		"crc-32": "^1.2.0",
 		"css-loader": "0.28.10",
 		"debug": "3.1.0",
 		"deep-equal": "1.0.1",
diff --git a/src/api/models/othello-game.ts b/src/api/models/othello-game.ts
index ab90cffa44..788fb5cba6 100644
--- a/src/api/models/othello-game.ts
+++ b/src/api/models/othello-game.ts
@@ -35,6 +35,9 @@ export interface IGame {
 	};
 	form1: any;
 	form2: any;
+
+	// ログのposを文字列としてすべて連結したもののCRC32値
+	crc32: string;
 }
 
 /**
diff --git a/src/api/stream/othello-game.ts b/src/api/stream/othello-game.ts
index 888c599338..e2ecce38ea 100644
--- a/src/api/stream/othello-game.ts
+++ b/src/api/stream/othello-game.ts
@@ -1,5 +1,6 @@
 import * as websocket from 'websocket';
 import * as redis from 'redis';
+import * as CRC32 from 'crc-32';
 import Game, { pack } from '../models/othello-game';
 import { publishOthelloGameStream } from '../event';
 import Othello from '../../common/othello/core';
@@ -50,6 +51,11 @@ export default function(request: websocket.request, connection: websocket.connec
 				if (msg.pos == null) return;
 				set(msg.pos);
 				break;
+
+			case 'check':
+				if (msg.crc32 == null) return;
+				check(msg.crc32);
+				break;
 		}
 	});
 
@@ -231,11 +237,12 @@ export default function(request: websocket.request, connection: websocket.connec
 				}
 				//#endregion
 
-				publishOthelloGameStream(gameId, 'started', await pack(gameId));
+				publishOthelloGameStream(gameId, 'started', await pack(gameId, user));
 			}, 3000);
 		}
 	}
 
+	// 石を打つ
 	async function set(pos) {
 		const game = await Game.findOne({ _id: gameId });
 
@@ -278,10 +285,13 @@ export default function(request: websocket.request, connection: websocket.connec
 			pos
 		};
 
+		const crc32 = CRC32.str(game.logs.map(x => x.pos.toString()).join('') + pos.toString());
+
 		await Game.update({
 			_id: gameId
 		}, {
 			$set: {
+				crc32,
 				is_ended: o.isEnded,
 				winner_id: winner
 			},
@@ -300,4 +310,20 @@ export default function(request: websocket.request, connection: websocket.connec
 			});
 		}
 	}
+
+	async function check(crc32) {
+		const game = await Game.findOne({ _id: gameId });
+
+		if (!game.is_started) return;
+
+		// 互換性のため
+		if (game.crc32 == null) return;
+
+		if (crc32 !== game.crc32) {
+			connection.send(JSON.stringify({
+				type: 'rescue',
+				body: await pack(game, user)
+			}));
+		}
+	}
 }
diff --git a/src/web/app/common/views/components/othello.game.vue b/src/web/app/common/views/components/othello.game.vue
index 77be458879..01148f193e 100644
--- a/src/web/app/common/views/components/othello.game.vue
+++ b/src/web/app/common/views/components/othello.game.vue
@@ -37,17 +37,20 @@
 
 <script lang="ts">
 import Vue from 'vue';
+import * as CRC32 from 'crc-32';
 import Othello, { Color } from '../../../../../common/othello/core';
 import { url } from '../../../config';
 
 export default Vue.extend({
-	props: ['game', 'connection'],
+	props: ['initGame', 'connection'],
 
 	data() {
 		return {
+			game: null,
 			o: null as Othello,
 			logs: [],
-			logPos: 0
+			logPos: 0,
+			pollingClock: null
 		};
 	},
 
@@ -104,6 +107,8 @@ export default Vue.extend({
 	},
 
 	created() {
+		this.game = this.initGame;
+
 		this.o = new Othello(this.game.settings.map, {
 			isLlotheo: this.game.settings.is_llotheo,
 			canPutEverywhere: this.game.settings.can_put_everywhere,
@@ -116,14 +121,29 @@ export default Vue.extend({
 
 		this.logs = this.game.logs;
 		this.logPos = this.logs.length;
+
+		// 通信を取りこぼしてもいいように定期的にポーリングさせる
+		if (this.game.is_started && !this.game.is_ended) {
+			this.pollingClock = setInterval(() => {
+				const crc32 = CRC32.str(this.logs.map(x => x.pos.toString()).join(''));
+				this.connection.send({
+					type: 'check',
+					crc32
+				});
+			}, 10000);
+		}
 	},
 
 	mounted() {
 		this.connection.on('set', this.onSet);
+		this.connection.on('rescue', this.onRescue);
 	},
 
 	beforeDestroy() {
 		this.connection.off('set', this.onSet);
+		this.connection.off('rescue', this.onRescue);
+
+		clearInterval(this.pollingClock);
 	},
 
 	methods: {
@@ -181,6 +201,27 @@ export default Vue.extend({
 					this.game.winner = null;
 				}
 			}
+		},
+
+		// 正しいゲーム情報が送られてきたとき
+		onRescue(game) {
+			this.game = game;
+
+			this.o = new Othello(this.game.settings.map, {
+				isLlotheo: this.game.settings.is_llotheo,
+				canPutEverywhere: this.game.settings.can_put_everywhere,
+				loopedBoard: this.game.settings.looped_board
+			});
+
+			this.game.logs.forEach(log => {
+				this.o.put(log.color, log.pos);
+			});
+
+			this.logs = this.game.logs;
+			this.logPos = this.logs.length;
+
+			this.checkEnd();
+			this.$forceUpdate();
 		}
 	}
 });
diff --git a/src/web/app/common/views/components/othello.gameroom.vue b/src/web/app/common/views/components/othello.gameroom.vue
index 9f4037515a..9df458f644 100644
--- a/src/web/app/common/views/components/othello.gameroom.vue
+++ b/src/web/app/common/views/components/othello.gameroom.vue
@@ -1,7 +1,7 @@
 <template>
 <div>
 	<x-room v-if="!g.is_started" :game="g" :connection="connection"/>
-	<x-game v-else :game="g" :connection="connection"/>
+	<x-game v-else :init-game="g" :connection="connection"/>
 </div>
 </template>