cscの作法 その315

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

# 練習問題
websocket serverを実装せよ。
俺言語を返却、せよ。


# サンプルコード

```

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;

namespace WebSocketServer
{
	internal class Program : IDisposable {
		private static WebSocket webSocket;
		private static byte[] ram = new byte[256];
		private static byte Rmd = 233;
		private static byte Bnd = 234;
		private static byte Pcc = 235;
		private static byte Lbf = 237;
		private static byte Ptr;
		private static byte Cur;
		private static byte c;
		private static byte adr;
		private static byte adr2;
		private static byte val;
		private static string res = "";
		private static byte READB(byte adr) {
			byte v = ram[adr];
			return v;
		}
		private static void WRITEB(byte adr, byte data) {
			ram[adr] = data;
		}
		private static void putchar(byte b) {
			char c = Convert.ToChar(b);
			res += c;
		}
		private static void put(byte b) {
			res += b + " ";
		}
		private static void crlf() {
			putchar(Convert.ToByte('\r'));
			putchar(Convert.ToByte('\n'));
		}
		private static byte putl(byte pt, byte d) {
			while (READB(pt) != d)
			{
				putchar(READB(pt++));
			}
			return pt;
		}
		private static void putlp(byte d) {
			while (READB(Ptr) != d)
			{
				putchar(READB(Ptr++));
			}
		}
		private static byte nxtln(byte pt) {
			for (pt += 1; READB(pt++) != Convert.ToByte('\0');)
				;
			return pt;
		}
		private static bool fndln() {
			for (Cur = 0; Cur != READB(Bnd); Cur = nxtln(Cur))
			{
				if (READB(Cur) == READB(Pcc))
					return true;
			}
			return false;
		}
		private static bool nxline() {
			for (Cur = 0; Cur != READB(Bnd); Cur = nxtln(Cur))
			{
				if (READB(Cur) > READB(Pcc))
					return true;
			}
			return false;
		}
		private static bool num() {
			if (48 <= (READB(Ptr)) && (READB(Ptr)) <= 57)
				return true;
			else
				return false;
		}
		private static bool getnm2() {
			byte ch;
			if (!num())
				return false;
			byte n = 0;
			do
			{
				n *= 10;
				ch = READB(Ptr++);
				n += Convert.ToByte(ch - 48);
			} while (num());
			val = n;
			return true;
		}
		private static void getvr2() {
			byte cc = READB(Ptr);
			if (cc == Convert.ToByte('a'))
				adr2 = 230;
			else if (cc == Convert.ToByte('#'))
				adr2 = Pcc;
			else if (cc == Convert.ToByte('b'))
				adr2 = 231;
			else if (cc == Convert.ToByte('c'))
				adr2 = 232;
			else if (cc == Convert.ToByte('%'))
				adr2 = Rmd;
			else
				adr2 = 230;
		}
		private static void getvr() {
			c = READB(Ptr);
			if (c == Convert.ToByte('a'))
				adr = 230;
			else if (c == Convert.ToByte('#'))
				adr = Pcc;
			else if (c == Convert.ToByte('b'))
				adr = 231;
			else if (c == Convert.ToByte('c'))
				adr = 232;
			else
				adr = 230;
		}
		private static void term() {
			byte cc;
			cc = READB(Ptr++);
			byte val2 = val;
			factr();
			if (cc == Convert.ToByte('*'))
			{
				val = Convert.ToByte(val2 * val);
			}
			else if (cc == Convert.ToByte('+'))
			{
				val = Convert.ToByte(val2 + val);
			}
			else if (cc == Convert.ToByte('-'))
			{
				val = Convert.ToByte(val2 - val);
			}
			else if (cc == Convert.ToByte('/'))
			{
				WRITEB(Rmd, Convert.ToByte(val2 % val));
				val = Convert.ToByte(val2 / val);
			}
			else if (cc == Convert.ToByte('='))
			{
				if (val2 == val)
					val = 1;
				else
					val = 0;
			}
			else if (cc == Convert.ToByte('^'))
			{
				val = Convert.ToByte(val2 ^ val);
			}
			else if (cc == Convert.ToByte('&'))
			{
				val = Convert.ToByte(val2 & val);
			}
			else if (cc == Convert.ToByte('|'))
			{
				val = Convert.ToByte(val2 | val);
			}
			else if (cc == Convert.ToByte('>'))
			{
				if (val2 >= val)
					val = 1;
				else
					val = 0;
			}
			else
			{
				if (val2 < val)
					val = 1;
				else
					val = 0;
			}
		}
		private static void factr() {
			byte cc;
			if (READB(Ptr) == Convert.ToByte('\0'))
			{
				val = 0;
				return;
			}
			if (getnm2())
				return;
			cc = READB(Ptr++);
			if (cc == Convert.ToByte('$'))
			{
				Random r = new Random();
				val = Convert.ToByte(r.Next(10));
			}
			else if (cc == Convert.ToByte(':'))
			{
				val = Convert.ToByte('\t');
			}
			else if (cc == Convert.ToByte(';'))
			{
				val = Convert.ToByte('\n');
			}
			else
			{
				Ptr--;
				getvr2();
				val = READB(adr2);
				Ptr++;
			}
		}
		private static void expr() {
			byte cc;
			factr();
			while ((cc = READB(Ptr)) != Convert.ToByte('\0'))
			{
				term();
			}
			Ptr++;
		}
		private static void ordr() {
			getvr();
			Ptr++;
			Ptr++;
			if (READB(Ptr) == Convert.ToByte('"'))
			{
				Ptr++;
				putlp(Convert.ToByte('"'));
			}
			else
			{
				expr();
				if (c == Convert.ToByte('$'))
				{
				}
				else if (c == Convert.ToByte('?'))
				{
					put(val);
				}
				else
				{
					WRITEB(adr, val);
				}
			}
		}
		private static void run(string str) {
			byte j;
			res = "";
			Ptr = Lbf;
			for (j = 0; j < str.Length; j++)
			{
				WRITEB(Ptr++, Convert.ToByte(str[j]));
			}
			WRITEB(Ptr++, Convert.ToByte('\0'));
			byte ima = 0;
			Ptr = Lbf;
			if (!getnm2())
			{
				Ptr = Lbf;
				WRITEB(Pcc, 0);
				for ( ; ; )
				{
					ima = READB(Pcc);
					ordr();
					if (READB(Pcc) == 0 && ima == 0)
					{
						break;
					}
					else
					{
						if (READB(Pcc) == 0)
							WRITEB(Pcc, ima);
						if (READB(Pcc) == 1)
							ima = 1;
						if (READB(Pcc) == ima)
						{
							if (nxline())
							{
								WRITEB(Pcc, READB(Cur));
								Ptr = Convert.ToByte(Cur + 2);
							}
							else
							{
								break;
							}
						}
						else
						{
							if (fndln())
							{
								WRITEB(Pcc, READB(Cur));
								Ptr = Convert.ToByte(Cur + 2);
							}
							else
							{
								break;
							}
						}
					}
				}
			}
			else
			{
				if (val == 0)
				{
					byte pt;
					for (pt = 0; pt < READB(Bnd); pt++)
					{
						put(READB(pt));
						pt += 1;
						pt = putl(pt, Convert.ToByte('\0'));
						crlf();
					}
				}
				else
				{
					byte src,
						dst,
						m,
						h;
					byte f = 0;
					WRITEB(Pcc, val);
					if (fndln())
					{
						src = nxtln(Cur);
						for (dst = Cur; src != READB(Bnd); dst++, src++)
						{
							WRITEB(dst, READB(src));
						}
						WRITEB(Bnd, dst);
					}
					if (nxline())
					{
						f = 1;
					}
					src = READB(Bnd);
					for (m = 2, h = Ptr; READB(h) != Convert.ToByte('\0'); m++)
					{
						h++;
					}
					if (m > 2)
					{
						WRITEB(Bnd, Convert.ToByte(src + m));
						if (f == 1)
						{
							Cur--;
							for (dst = READB(Bnd); src != Cur; dst--, src--)
							{
								WRITEB(dst, READB(src));
							}
							src++;
						}
						WRITEB(src, val);
						src += 1;
						byte k;
						for (k = 1; k < m; k++)
						{
							WRITEB(src++, READB(Ptr++));
						}
					}
				}
			}
		}
		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(">");
				run(message);
				buffer = Encoding.UTF8.GetBytes(res);
				byteArray = new ArraySegment<byte>(buffer);
				await webSocket.SendAsync(byteArray, WebSocketMessageType.Text, true, CancellationToken.None);
				Console.WriteLine(res);
				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();
			}
		}
	}
}





```

以上。