cscの作法 その314

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
websocket serverを実装せよ。
forthを返却、せよ。
forthで数9を4個つかって1から15までの数を表す式を実行せよ。


# 方針

```
9 9 - 9 9 / . # 1
9 9 / 9 9 / + . # 2
9 9 + 9 + 9 / . # 3
9 9 9 + 9 / dup + . # 4
9 9 9 + 9 / dup + - . # 5
9 dup 9 + 9 + 9 / - . # 6
9 9 9 + 9 / - . # 7
9 9 9 drop 9 / - . # 8
9 9 - 9 * 9 + . # 9
9 9 / 9 dup 9 / + . # 10
9 9 9 + 9 / + . # 11
9 dup 9 9 + + 9 / + . # 12
9 9 9 + 9 / dup + + . # 13
9 dup 9 9 + 9 / dup + - + . # 14
9 dup dup 9 + 9 + 9 / - + . # 15
```

# サンプルコード

```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Globalization;
using System.Collections;

namespace WebSocketServer
{
	internal class Program : IDisposable {
		private static Stack<int> stack = new Stack<int>();
		private static void add() {
			int top1 = stack.Pop();
			int top2 = stack.Pop();
			int v = top2 + top1;
			stack.Push(v);
		}
		private static void sub() {
			int top1 = stack.Pop();
			int top2 = stack.Pop();
			int v = top2 - top1;
			stack.Push(v);
		}
		private static void mul() {
			int top1 = stack.Pop();
			int top2 = stack.Pop();
			int v = top2 * top1;
			stack.Push(v);
		}
		private static void div() {
			int top1 = stack.Pop();
			int top2 = stack.Pop();
			int v = top2 / top1;
			stack.Push(v);
		}
		private static void dup() {
			int top1 = stack.Pop();
			stack.Push(top1);
			stack.Push(top1);
		}
		private static void drop() {
			int top1 = stack.Pop();
		}
		private static string get() {
			int top1 = stack.Pop();
			return top1.ToString();
		}
		private static void push(string s) {
			int v = Convert.ToInt32(s);
			stack.Push(v);
		}
		private static WebSocket webSocket;
		public async void Dispose() {
			if (webSocket != null)
			{
				Console.WriteLine("WebSocketサーバーからの切断");
				await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "WebSocketサーバーからの切断", CancellationToken.None);
				webSocket.Dispose();
			}
		}
		static async Task Receive() {
			while (true)
			{
				if (webSocket == null || (webSocket != null && webSocket.State != WebSocketState.Open))
				{
					Console.WriteLine("WebSocket接続がありません");
					Console.Write(">");
					return;
				}
				var buffer = new byte[1024];
				var byteArray = new ArraySegment<byte>(buffer);
				var ret = await webSocket.ReceiveAsync(byteArray, CancellationToken.None);
				if (ret.MessageType == WebSocketMessageType.Close)
				{
					Console.WriteLine("クライアントから切断されました");
					Console.Write(">");
					await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "クライアントから切断されました", CancellationToken.None);
					return;
				}
				if (ret.MessageType != WebSocketMessageType.Text)
				{
					Console.WriteLine("テキストデータではありません");
					Console.Write(">");
					await webSocket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "テキストデータではありません", CancellationToken.None);
					return;
				}
				int size = ret.Count;
				while (!ret.EndOfMessage)
				{
					if (buffer.Length <= size)
					{
						Console.WriteLine("バッファーオーバー");
						await webSocket.CloseAsync(WebSocketCloseStatus.InvalidPayloadData, "バッファーオーバー", CancellationToken.None);
						return;
					}
					byteArray = new ArraySegment<byte>(buffer, size, buffer.Length - size);
					ret = await webSocket.ReceiveAsync(byteArray, CancellationToken.None);
					size += ret.Count;
				}
				var message = Encoding.UTF8.GetString(buffer, 0, size);
				Console.WriteLine(message);
				Console.Write(">");
				string src = message;
				string str = "";
				string[] lines = src.Split(new string[] {
					" "
				}, StringSplitOptions.None);
				foreach (string s in lines)
				{
					switch (s)
					{
					case "+":
						add();
					break;
					case "-":
						sub();
					break;
					case "*":
						mul();
					break;
					case "/":
						div();
					break;
					case "dup":
						dup();
					break;
					case "drop":
						drop();
					break;
					case ".":
						str = get();
					break;
					default:
						push(s);
					break;
					}
				}
				buffer = Encoding.UTF8.GetBytes(str);
				byteArray = new ArraySegment<byte>(buffer);
				await webSocket.SendAsync(byteArray, WebSocketMessageType.Text, true, CancellationToken.None);
				Console.WriteLine(str);
				Console.Write(">");
			}
		}
		static async Task CreateWebSocketServerAndReceive() {
			var httpListener = new HttpListener();
			httpListener.Prefixes.Add("http://localhost:50002/");
			httpListener.Start();
			Console.WriteLine("WebSocket受付開始");
			while (true)
			{
				var httpListenerContext = await httpListener.GetContextAsync();
				if (!httpListenerContext.Request.IsWebSocketRequest)
				{
					Console.WriteLine("WebSocketでの接続ではありません");
					httpListenerContext.Response.StatusCode = 400;
					httpListenerContext.Response.Close();
					return;
				}
				var taskHttpListenerContext = await httpListenerContext.AcceptWebSocketAsync(null);
				if (webSocket != null)
				{
					webSocket.Dispose();
				}
				webSocket = taskHttpListenerContext.WebSocket;
				Console.WriteLine("WebSocket接続");
				Console.Write(">");
				var nowait = Receive();
			}
		}
		static void Main(string[] args) {
			Console.WriteLine("開始:CTRL+Cで停止してください");
			var nowait1 = CreateWebSocketServerAndReceive();
			using (var manualResetEvent = new ManualResetEvent(false))
			{
				manualResetEvent.WaitOne();
			}
		}
	}
}

```

以上。