C# : TCP Server using Completion port

class AsyncServerState
{
   public byte[] Buffer = new byte[512]; //buffer for network i/o
   public int DataSize = 0; //data size to be received by the server
  
   //flag that indicates whether prefix was received
   public bool DataSizeReceived = false;

   public MemoryStream Data = new MemoryStream(); //place where data is stored
   public SocketAsyncEventArgs ReadEventArgs = new SocketAsyncEventArgs();
   public Socket Client;
}

To preserve application state between async operations SocketAsyncEventArgs.UserToken is used.

/// 
/// Async server sample, demonstates usage of XxxAsync methods
/// 
class AsyncServer
{
  Socket listeningSocket;
  List<byte[]> messages = new List<byte[]>();
  const int PrefixSize = 4;
      
  SocketAsyncEventArgs acceptEvtArgs;
        
  public AsyncServer()
  {
     this.listeningSocket = new Socket(AddressFamily.InterNetwork,
              SocketType.Stream, ProtocolType.Tcp);
     this.acceptEvtArgs = new SocketAsyncEventArgs();
  }
      
  public void Start(IPEndPoint listeningAddress)
  {
     acceptEvtArgs.Completed += new EventHandler(
                                        Accept_Completed);

     listeningSocket.Bind(listeningAddress);
     listeningSocket.Listen(1);

     ProcessAccept(acceptEvtArgs);
  }

  /// 
  /// Accept completion handler
  /// 
  void Accept_Completed(object sender, SocketAsyncEventArgs e)
  {
     if (e.SocketError == SocketError.Success)
     {
        Socket client = e.AcceptSocket;
        AsyncServerState state = new AsyncServerState();
        state.ReadEventArgs.AcceptSocket = client;
        state.ReadEventArgs.Completed += new EventHandler(
                                                 IO_Completed);
        state.ReadEventArgs.UserToken = state;
        state.Client = client;
        state.ReadEventArgs.SetBuffer(state.Buffer, 0, state.Buffer.Length);

        if (!client.ReceiveAsync(state.ReadEventArgs))
        {   //call completed synchonously
            ProcessReceive(state.ReadEventArgs);
        }
     }
     ProcessAccept(e);
  }

  private void ProcessAccept(SocketAsyncEventArgs e)
  {
      e.AcceptSocket = null;
      if (!listeningSocket.AcceptAsync(acceptEvtArgs))
      {   //operation completed synchronously
          Accept_Completed(null, acceptEvtArgs);
      }
  }

  /// 
  /// Genereic I/O completion handler
  /// 
  void IO_Completed(object sender, SocketAsyncEventArgs e)
  {
      switch (e.LastOperation)
      {
          case SocketAsyncOperation.Receive:
              ProcessReceive(e);
              break;
          case SocketAsyncOperation.Send:
              ProcessSend(e);
              break;
          default:
              throw new NotImplementedException("The code will "
                   +"handle only receive and send operations");
      }
  }

  /// 
  /// In future will process server send operations
  /// 
  private void ProcessSend(SocketAsyncEventArgs e) { }

  /// 
  /// Implements server receive logic
  /// 
  private void ProcessReceive(SocketAsyncEventArgs e)
  {
      //single message can be received using several receive operation
      AsyncServerState state = e.UserToken as AsyncServerState;

      if (e.BytesTransferred <= 0 || e.SocketError != SocketError.Success)        {            CloseConnection(e);        }        int dataRead = e.BytesTransferred;        int dataOffset = 0;        int restOfData = 0;         while (dataRead > 0)
      {
          if (!state.DataSizeReceived)
          {
              //there is already some data in the buffer
              if (state.Data.Length > 0)
              {
                  restOfData = PrefixSize - (int)state.Data.Length;
                  state.Data.Write(state.Buffer, dataOffset, restOfData);
                  dataRead -= restOfData;
                  dataOffset += restOfData;
              }
              else if (dataRead >= PrefixSize)
              {   //store whole data size prefix
                  state.Data.Write(state.Buffer, dataOffset, PrefixSize);
                  dataRead -= PrefixSize;
                  dataOffset += PrefixSize;
              }
              else
              {   // store only part of the size prefix
                  state.Data.Write(state.Buffer, dataOffset, dataRead);
                  dataOffset += dataRead;
                  dataRead = 0;
              }

              if (state.Data.Length == PrefixSize)
              {   //we received data size prefix
                  state.DataSize = BitConverter.ToInt32(state.Data.GetBuffer(), 0);
                  state.DataSizeReceived = true;

                  state.Data.Position = 0;
                  state.Data.SetLength(0);
              }
              else
              {   //we received just part of the headers information
                  //issue another read
                  if (!state.Client.ReceiveAsync(state.ReadEventArgs))
                      ProcessReceive(state.ReadEventArgs);
                      return;
              }
          }

          //at this point we know the size of the pending data
          if ((state.Data.Length + dataRead) >= state.DataSize)
          {   //we have all the data for this message

              restOfData = state.DataSize - (int)state.Data.Length;

              state.Data.Write(state.Buffer, dataOffset, restOfData);
              Console.WriteLine("Data message received. Size: {0}",
                                    state.DataSize);

              dataOffset += restOfData;
              dataRead -= restOfData;

              state.Data.SetLength(0);
              state.Data.Position = 0;
              state.DataSizeReceived = false;
              state.DataSize = 0;

              if (dataRead == 0)
              {
                  if (!state.Client.ReceiveAsync(state.ReadEventArgs))
                      ProcessReceive(state.ReadEventArgs);
                      return;
              }
              else
                  continue;
          }
          else
          {   //there is still data pending, store what we've
              //received and issue another BeginReceive
              state.Data.Write(state.Buffer, dataOffset, dataRead);

              if (!state.Client.ReceiveAsync(state.ReadEventArgs))
                  ProcessReceive(state.ReadEventArgs);

              dataRead = 0;
          }
      }
  }

  private void CloseConnection(SocketAsyncEventArgs e)
  {
      AsyncServerState state = e.UserToken as AsyncServerState;

      try
      {
          state.Client.Shutdown(SocketShutdown.Send);
      }
      catch (Exception) { }
          
      state.Client.Close();
  }
}

Recompile : MonoGame.Framework.dll

  1. Download the sources from the following link (also available at the Code tab above):
    https://github.com/mono/MonoGame/archive/develop.zip
  2. Open MonoGame.Framework.Android.sln in Visual Studio.
  3. If you already installed MonoAndroid, the new MonoAndroid dll will be automatically referenced for you,
    just click Project > Build Solution.
    The bin folder will contain the new MonoGame dll.

4. Copy file MonoGame.Framework.dll, Lidgren.Network.dll from MonoGame-develop/MonoGame.Framework/Bin/Android/Release    -> C:\Program Files (x86)\MonoGame\v3.0\Assemblies\Android\

ติดตั้ง Windows7 ใหม่ให้กับเครื่องเก่า

วันนี้ทำการติดตั้งระบบปฏิบัติการ Windows7 Ultimate 64 bit ใหม่อีกครั้ง เพื่อใช้สำหรับการพัฒนาเกมออนไลน์บนมือถือ โดยขั้นตอนการติดตั้งมีดังต่อไปนี้

1. ติดตั้ง KKD Windows7 Ultimate

2. ติดตั้ง ATI Graphic Driver

3. ติดตั้ง Google Chrome Web Browser

4. ติดตั้ง Microsoft Visual Studio 2010 64bit

5. อัพเดท NOD32 จากเวปไซต์ jkdramas.com/nodup/Header.htm

6. Eclipse Classic 4.2.2 Windows 64 bit

6.1 Setup JRE-7u17-windows-x64.exe

6.2 Eclipse -> Install new software -> https://dl-ssl.google.com/android/eclipse/

7. ติดตั้ง Samsung Kies

8. ติดตั้ง MonoGame SDK สำหรับ Visual Studio 2010

9. ติดตั้ง MonoGame SDK สำหรับ Xamarin

โครงการปั้นลูกให้เป็นโปรแกรมเมอร์

ช่วงเวลาปิดเทอม 3 เดือน ตั้งแต่ มีนาคม-พฤษภาคม 2556 นับเป็นช่วงเวลาที่ดีที่จะปูพื้นฐานให้กับลูกๆ ทั้งสองคน เพื่อให้เข้าใจกับวิธีการเขียนโปรแกรมบนมือถือแอนดรอยด์ ด้วยโปรแกรม Xamarin C#

1. ติดตั้งโปรแกรม Xamarin บน Windows 7 บน Notebook ตัวเล็ก

2. ติดตั้ง Samsung Kies เพื่อใช้ในการ Sync ข้อมูลระหว่าง Notebook กับมือถือ

3.  Hello Android ตัวแรกสามารถรันได้ทั้งบน Emulator และบนมือถือจริง

หมายเหตุ : ที่มือถือจะต้องทำการเลือก Unknown Resource for Development ด้วย

225492_424961680922641_873460589_n

เริ่มต้นกับ MonoDevelop+Xamarin

MonoDevelop 4.0 : Website คือ โปรแกรมสำหรับใช้ในการพัฒนาแอพพลิเคชันด้วย C# บน Windows, Linux, Mac OSX [ฟรี]

Xamarin 2.0 : Website คือส่วนที่ต่อยอดมาจาก MonoDevelop อีกทีหนึ่งโดย GUI พัฒนามาจาก Qt ซึ่งประกอบไปด้วยคอมโพเนนท์ที่ใช้สำหรับการพัฒนาแอพบน Android, iOS และ MAC [เสียเงิน $299, $999]

Massive Multiplayer Online Game Engine for Mobile

IMG_0440sm

 

วันนี้นั่งรวบรวมตำราเกี่ยวกับงานเน็ตเวอร์คที่ซื้อมาจากประเทศเกาหลีใต้ และหนังสือไทย มากองรวมกันดู เพื่อที่จะได้กำหนดแนวทางการพัฒนางานเน็ตเวอร์ค สำหรับใช้ในเกมออนไลน์บนมือถือ

โดยส่วนของ Server จะตั้งเป้าหมายไว้ที่ OS Windows เป็นหลัก เพื่อที่จะใช้งานในส่วนของ IOCP บน Windows ทำให้สามารถรองรับจำนวนผู้เล่นได้เป็นจำนวนมาก โดยโปรโตคอลที่รองรับ ก็จะมี Tcp และ Udp

และในส่วนของ Client นั้น ก็จะสามารถใช้งานได้ทั้งบน PC, MAC, iOS, Android โดยการเขียนด้วย Mono 2.0 บน Unity3D เป็นหลัก

Unity3D : Asset bundle

TLlist<string> fileList;
int n=0;
IEnumerator OnClick()
{
WWW image = new www(fileList[n++]);
yield return image;
obj.mainTexture = image.texture;

n = (n>=fileList.Length-1)?0:n;
Resources.UnloadUnusedAssets();
}
这样可以保证内存里始终只有一个巨型Texture Asset资源,也不用代码追踪上一个加载的Texture Asset,但是速度比较慢
或者:
IEnumerator OnClick()
{
WWW image = new www(fileList[n++]);
yield return image;
Texture tex = obj.mainTexture;
obj.mainTexture = image.texture;

n = (n>=fileList.Length-1)?0:n;
Resources.UnloadAsset(tex);
}
หัวข้อการสนทนา ::.

http://game.ceeger.com/forum/read.php?tid=4394

Unity3D : Application.dataPath

พาธสำหรับ dataPath ::.

Unity Editor:<path tp project folder>/Assets
Mac player:<path to player app bundle>/Contents
iPhone player:<path to player app bundle>/<AppName.app>/Data
Win player:<path to executablename_Data folder>
Web player:The absolute url to the player data file folder (without the actual data file name)

http://game.ceeger.com/forum/read.php?tid=4451