title: C# basic Socket programming using Packets
body: <p>This is not actually a question. I'm trying to organize what I've learned about this subject this year. Since I am a beginner in C#, I had lots of difficulties doing this. But thanks to Stack Overflow and a lecture about packets in class, I was able to get enough information to write a program using multiple types of packets, and connections. This script is for beginners who do not know what to do about sockets.  </p>
  
  <p>The concept of sending a packet seems to be sending a whole class over the connection. Not writing the data directly to the stream. So, I have to make a DLL(Class Library) file which defines the packet class, and the derived classes of the packet class. </p>
  
  <p>I'll write a simple code for the Packet.dll, which will be having one type of packet, the Login class.</p>
  
  <p>*To make a DLL file, simply make a C# Class Library File on the VS. To compile it, press F7.</p>
  
  <p>"Project Packet, Packet.cs"</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.IO;
  using System.Runtime.Serialization.Formatters.Binary; 
  
  namespace Packet
  
  {
      public enum PacketType
      {
  
      initType = 0, //it's nothing on this code.
      login
  }
  
  [Serializable]
  public class Packet
  {
      public int Length;
      public int Type;
  
      public Packet() {
  
          this.Length = 0;
          this.Type = 0;
  
  
      }
  
      public static byte[] Serialize(Object o) {
  
          MemoryStream ms = new MemoryStream(1024 * 4); //packet size will be maximum of 4KB.
          BinaryFormatter bf = new BinaryFormatter();
          bf.Serialize(ms, o);
          return ms.ToArray();
  
      }
  
      public static Object Desirialize(byte[] bt) {
  
          MemoryStream ms = new MemoryStream(1024 * 4);//packet size will be maximum of 4KB.
  
          foreach( byte b in bt){
  
              ms.WriteByte(b);
  
          }
  
          ms.Position = 0;
          BinaryFormatter bf = new BinaryFormatter();
          object obj = bf.Deserialize(ms);
          ms.Close();
          return obj;
  
      }
  }
  }//end of Packet.cs
  </code></pre>
  
  <p>add a new class for this Project Packet, "Login.cs".</p>
  
  <p>"Project Packet, Login.cs"</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  
  namespace Packet
  {
  
      [Serializable]  //to serialize this class, this statement is essential.
     public class Login :Packet  //derived class of Packet.cs. Must be public.
      {
          public string id_str; //id
          public string pw_str; //pw
  
          public Login(string id, string pw) { //constructer to make the code more shorter.
  
              this.id_str = id;
              this.pw_str = pw;
  
          }
      }
  }//end of Login.cs
  </code></pre>
  
  <p>After you are finished with this, press F7 to compile, and you will get Packet.dll on your Debug folder of the Packet project file.
   This is all about the Packet class. If you want to add more classes to serialize, just add a new class, and add a enum value on the PacketType. </p>
  
  <p>Next, I'll write a short example source for using the Packet class. 
  Although it's a simple source using only one connection, and using only one type of packet, it will be written in multiple threads.  </p>
  
  <p>The original of this source which I wrote has many types of packets, and is expected to get multiple connections from multiple users, so I made the class "UserSocket" to make an instance of a connected user. And also, it will have the receiving thread function(A thread function for receiving packets from the client.) in another class "MessageThread.cs".</p>
  
  <p>"Project Server, Form1.cs" //a Windows Form Project, which only has a textBox named textBox1. </p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Windows.Forms;
  using System.Threading;
  using System.Net;
  using System.Net.Sockets;
  using Packet; //to add this, right click your project viewer and reference add Packet.dll.
  using System.IO;  
  
  namespace Server
  {
      public partial class Form1 : Form
      {
  
          private TcpListener server_Listener;
  
          public List&lt;UserSocket&gt; user_list = new List&lt;UserSocket&gt;(); //list to store user instances
  
          private Thread server_Thread; //thread for getting connections.
  
          public void setLog(string msg) //a function to write string on the Form1.textBox1.
          {
              this.BeginInvoke((MethodInvoker)(delegate()
              {
                  textBox1.AppendText(msg + "\n");
              }));
  
          } 
  
  private void Form1_Load(object sender, EventArgs e)
  {
  
      server_Thread = new Thread(new ThreadStart(RUN)); //starts to wait for connections.
      server_Thread.Start();
  
  }
  
          public void RUN() // Thread function to get connection from client. 
          {
  
              server_Listener = new TcpListener(7778);
              server_Listener.Start();
  
  
              while (true)
              {
  
  
                  this.BeginInvoke((MethodInvoker)(delegate()
                  {
                      textBox1.AppendText("Waiting for connection\n");
  
                  }));
  
                  UserSocket user = new UserSocket(); Make an instance of UserSocket
                  user.UserName = " ";
                  try
                  {
                      user.client = server_Listener.AcceptSocket();
  
                  }
                  catch
                  {
                      break;
                  }
  
                  if (user.client.Connected)
                  {
  
                      user.server_isClientOnline = true;
                      this.BeginInvoke((MethodInvoker)(delegate()
                      {
                          textBox1.AppendText("Client Online\n");
  
                      }));
                      user.server_netStream = new NetworkStream(user.client); //connect stream.
                      user_list.Add(user);
                      MessageThread mThread = new MessageThread(user, this, user_list); //make an instance of the MessageThread. 
  
  
  
                      user.receiveP = new Thread(new ThreadStart(mThread.RPACKET)); //run the receiving thread for user. 
                      user.receiveP.Start();
  
                  }
  
              }
  
          } //end of Form1.cs
  </code></pre>
  
  <p>"Project Server, UserSocket.cs"</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Net;
  using System.Net.Sockets;
  using System.IO;
  using System.Threading;
  using Packet;
  
  namespace Server
  {
      public class UserSocket //Just a Class to make an instance of the connected user. 
      {
          public NetworkStream server_netStream;
  
          public bool server_isClientOnline = false;
          public byte[] sendBuffer = new byte[1024 * 4];
          public byte[] readBuffer = new byte[1024 * 4];
  
          public string UserName = null; //Not in this code, but on the original, used to identify user.
  
          public Login server_LoginClass;
  
          public Socket client = null;
  
      }
  }//end of UserSocket.cs
  </code></pre>
  
  <p>"Project Server, MessageThread.cs"</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Net;
  using System.Net.Sockets;
  using System.Threading;
  using Packet;
  using System.IO;
  
  
  namespace Server
  {
      public class MessageThread //A Class for threads for each users. 
      {
          UserSocket uzr; 
          Form1 f;
          List&lt;UserSocket&gt; user_list = new List&lt;UserSocket&gt;();
  
          public MessageThread(UserSocket u, Form1 formget, List&lt;UserSocket&gt; u_l) //Constructer. 
          {
              uzr = u;
              f = formget;
              this.user_list = u_l;
          }
  
          public void RPACKET() //Thread function for receiving packets. 
          {
  
              f.setLog("rpacket online");
  
              int read = 0;
  
              while (uzr.server_isClientOnline)
              {
  
                  try
                  {
                      read = 0;
                      read = uzr.server_netStream.Read(uzr.readBuffer, 0, 1024 * 4);
                      if (read == 0)
                      {
                          uzr.server_isClientOnline = false;
                          break;
                      }
                  }
                  catch
                  {
                      uzr.server_isClientOnline = false;
                      uzr.server_netStream = null;
                  }
  
                  Packet.Packet packet = (Packet.Packet)Packet.Packet.Desirialize(uzr.readBuffer);
  //Deserialize the packet to a Packet.cs Type. It's because the packet.Type is in the super class. 
  
                  switch ((int)packet.Type)
                  {
                      case (int)PacketType.login: //If the PacketType is "login"
                          {
  
                              uzr.server_LoginClass = (Login)Packet.Packet.Desirialize(uzr.readBuffer);
  
  
                                  f.setLog("ID : " + uzr.server_LoginClass.id_str + " PW : " + uzr.server_LoginClass.pw_str); 
                                  uzr.UserName=uzr.server_LoginClass.id_str;                             
  
                          }
  
                  }
              }
  
          }
  
  
      }
  }
  </code></pre>
  
  <p>This will be all for the Server part. It starts a listening thread on the form_load to get connections, and if it's connected to a client, it will make an instance of UserSocket, and the connection will be made by the UserSocket.client(Socket client). And it will bind the socket with the NetworkStream of the UserSocket, and start a listening thread. 
   The listening thread will deserialize packets received by the client, and assign the received class to a member class of UserSocket. </p>
  
  <p>Next, it will be the sending part of this script. The client part.(On the original source, it can send, and also receive packets from the server, but on this script, I'll just make it send a packet. To receive a packet, just make a thread, and a thread function simular to the server on the main page.</p>
  
  <p>"Project Client, Form1.cs"</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Windows.Forms;
  using System.Threading;
  using System.Net;
  using System.Net.Sockets;
  using Packet;
  using System.IO;
  
  namespace Client
  {
      public partial class Form1 : Form //A Simple Windows Form Project with Two TextBoxes, and a Button
      {
          private string myid;
          private NetworkStream client_Netstream;
  
          private byte[] sendBuffer = new byte[1024 * 4];
          private byte[] receiveBuffer = new byte[1024 * 4];
          private TcpClient client_tcpClient;
  
          private bool client_isOnline = false;
  
          public Login login;
  
          private void Form1_Load(object sender, EventArgs e) 
          {
              //On Form1 Load, It will connect to the server directly. So, the Server must be active before executing the client. 
              this.client_tcpClient = new TcpClient();
  
              try
              {
                  this.client_tcpClient.Connect("localhost", 7778);
  
              }
              catch
              {
  
                  MessageBox.Show("Connection Failure\n");
                  return;
              }
  
              this.client_isOnline = true;
              this.client_Netstream = this.client_tcpClient.GetStream();
  
          }  
  
          private void button1_Click(object sender, EventArgs e)
          {
  
              if (!this.client_isOnline)
                  return;
  
              login = new Login();
              login.Type = (int)PacketType.login; //Very essential. must be defined for the server to identify the packet. 
              login.id_str = this.textBox1.Text;
              login.pw_str = this.textBox2.Text;            
              Packet.Packet.Serialize(login).CopyTo(this.sendBuffer, 0);
          this.client_Netstream.Write(this.sendBuffer, 0, this.sendBuffer.Length);
          this.client_Netstream.Flush();
  
              for (int i = 0; i &lt; 1024 * 4; i++)
                  this.sendBuffer[i] = 0;
  
          }
  
  }
  
  }//End of Form1.cs
  </code></pre>
  
  <p>As I said above, this client won't have a receiving thread. So this is all for the client. 
  It connects to the server on form load, and if you press the button1, the value of textbox1, and textbox2 will be sent to the server as a serialized packet, PacketType of 'login'. On this example the client just sends two variables, but it can send bigger classes such as classes with Lists. </p>
  
  <p>This is all I can explain about socket programming on C# using Packets. I tried to make it simple, but I couldn't make it shorter. For begginers like me, if you have a question, please leave a comment, and for more skilled experts, if this code needs modification for more efficient coding, please tell me by answering this script.  </p>