見出し画像

今話題のChatGTPでC#プログラムを作成してみる

「自動売買システム日経225ミニ専用をC#で作る」のロジックでリモートホストに接続するTcpClientがある。
自動売買システムが稼働中リモートホストが切断した場合TcpClientはDisconnectになりシャットダウンになってしまう。そのため自動売買システムを再起動する必要があることが判明しました。
コードの修正をすることになったので今話題になっているCharGTPで作成してみることにした。サイトにいきTry ChatGTPで「send amessage.... 」に ”C#でTcp Socketを使って非同期のクライアントを作成してください”
と入力すると、C#でクライアントのソースを作成してくれた。 !!びっくりすごい感心した。
コードを見ると基本的なソースコードが作成されていた。それでは、自動取引の仕様条件を入力してみた。
1.”送信はいらない連続受信するコードを作成してください。” コードは一回受信して終了するコードを作成した。
2. 再度 ”このコードは1回の受信で終了してしまいます。連続受信で作成してください” と入力すると、
「申し訳ありません、前回の回答が不十分でした。以下は、C#でTcp socketを使った非同期処理で、連続で受信のみを行うクライアントの例です。」
のコメントがあり新しいソースコードを作成してくれた。
会話をするように次々と仕様を指定してコード作成依頼を行うと徐々に自分の必要なコードが作成されました。
下記コードがほぼ仕様に近いコードになりました。

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

class Client
{
    private const int BUFFER_SIZE = 1024;
    private byte[] buffer = new byte[BUFFER_SIZE];
    private Socket clientSocket;

    public async Task StartClientAsync(string ip, int port)
    {
        while (true)
        {
            try
            {
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await clientSocket.ConnectAsync(IPAddress.Parse(ip), port);
                Console.WriteLine("Connected to server!");

                while (true)
                {
                    int received = await clientSocket.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);

                    if (received == 0)
                    {
                        Console.WriteLine("Connection closed by remote host.");
                        break;
                    }

                    string message = System.Text.Encoding.ASCII.GetString(buffer, 0, received);
                    Console.WriteLine($"Received: {message}");
                }
            }
            catch (SocketException ex)
            {
                Console.WriteLine($"SocketException: {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception: {ex.Message}");
            }

            await Task.Delay(5000);
            Console.WriteLine("Trying to reconnect...");
        }
    }

    public async Task StopClientAsync()
    {
        if (clientSocket != null)
        {
            clientSocket.Shutdown(SocketShutdown.Both);
            await Task.Delay(500);
            clientSocket.Dispose();
        }
    }
}

このコードをサンプルにして「connected 通知イベント、Disconnected通知イベント、受信データをJSONコンバート、DataRecieve通知イベント等を追加した私流のコードを作成しました。

/// <summary>
    /// TcpClientクラス
    /// </summary>
    public class TcpClient
    {
        private static log4net.ILog _logger = log4net.LogManager.GetLogger(
                          System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        //private byte[] _buffer = new byte[1024];
        // 受信データのレスポンス
        private string response = string.Empty;
        private Socket client = null;
        private StateObject state = null;
        private string _host;
        private int _port;

        // 受信データイベント
        public event Action<object,EventArgs> Connected;
        public event Action<object, EventArgs> Disconnected;
        public event Action<object, TcpClientModel> DataReceived;
        
        public TcpClient()
        {
               
        }

        /// <summary>
        /// TcpClient スタート
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public async Task StartClient(string host, int port)
        {
            _host = host;
            _port = port;
            
            while (true)
            {
                try
                {
                    //コネクトできたない
                    _logger.Info(" Not connected ");
                    Disconnected?.Invoke(this, new EventArgs());
                    
                    //リモートホストに接続する
                    _logger.Info("リモートホストに接続します。");
                    
                    client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                    client =  await ConnectAsync(host, port,3000);
                    
                    _logger.Info("connect 正常");

                    //イベントで正常接続出来た事を通知する
                    
                    Connected?.Invoke(this,new EventArgs());

                    // ソケット情報を保持する為のオブジェクトを生成
                    state = new StateObject();
                    state.workSocket = client;
                    response = string.Empty;


                    while (client.Connected)
                    {
                        // ソケット情報を保持する為のオブジェクトを生成
                        state = new StateObject();
                        state.workSocket = client;
                        response = string.Empty;

                        int received = await client.ReceiveAsync(new ArraySegment<byte>(state.buffer), SocketFlags.None);
                        if (received == 0)
                        {
                            //Console.WriteLine("Connection closed by remote host.");
                            Disconnected?.Invoke(this, new EventArgs());
                            _logger.Error("TcpClient受信エラー");
                            break;
                        }
                        response = Encoding.UTF8.GetString(state.buffer, 0, received);
                        TcpClientModel Tcpdata =
                            JsonConvert.DeserializeObject<TcpClientModel>(response);
                        
                        DataReceived?.Invoke(this,Tcpdata);

                        _logger.Info("Receive Data Send to ViewModel");

                        //Console.WriteLine($"Received: {response}");
                                 
                    }    
                }
                catch (SocketException ex)
                {
                    //Console.WriteLine($"Error receiving data from server: {ex.Message}");
                    await Task.Delay(2000);
                    Disconnected?.Invoke(this, new EventArgs());

                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Exception: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// リモートホストに接続する
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <param name="timeoutMs"></param>
        /// <returns></returns>
        public async Task<Socket> ConnectAsync(string host, int port, int timeoutMs)
        {
            while (true)
            {
                try
                {
                    // TCP/IPのソケットを作成
                    client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                    await client.ConnectAsync(host,port);

                    //リモートホストに接続完了
                    return client;
                }
                catch (SocketException ex)
                {
                    await Task.Delay(timeoutMs);
                }
            }
        }

        /// <summary>
        /// 非同期処理でソケット情報を保持する為のオブジェクト
        /// </summary>
        public class StateObject
        {
            // 受信バッファサイズ
            public const int BufferSize = 1024;

            // 受信バッファ
            public byte[] buffer = new byte[BufferSize];

            // 受信データ
            public StringBuilder sb = new StringBuilder();

            // ソケット
            public Socket workSocket = null;
        }

        /// <summary>
        /// 受信終了メソッド
        /// </summary>
        public void Disconnect()
        {
            if (client.Connected)
            {
                client.Shutdown(SocketShutdown.Both);
            }
            client.Close();
            Disconnected?.Invoke(this, EventArgs.Empty);
        }
    }

ChatGPTはすごい。でもきをつけましょう。うそもつくそうです!。


この記事が気に入ったらサポートをしてみませんか?