티스토리 뷰




Sample Image - maximum width is 600   pixels

<!-- Add the article text. Please use simple formatting (

, etc) -->

Introduction


Got Bored.

The Library Project


I created a ChatLibrary that will contain the valid commands and a Message that will contain the parsing.
Collapse


public enum Command
{
Login = 0,
PersonalMessage = 1,
ClientList = 2,
Conference = 3,
Logout = 4
};

public class Message
{
string strSender;
string strReceiver;
Command cmdMessageCommand;
string strMessageDetail;
public Message ()
{
}
public Message (byte [] rawMessage)
{
string strRawStringMessage = System.Text.Encoding.ASCII.GetString (rawMessage);
string [] strRawStringMessageArray = strRawStringMessage.Split(new char []{'|'});
this.strSender = strRawStringMessageArray[1];
this.strReceiver = strRawStringMessageArray[2];
this.cmdMessageCommand = (Command) Convert.ToInt32(strRawStringMessageArray[3]);
this.MessageDetail = strRawStringMessageArray[4];
}
...

public byte [] GetRawMessage ()
{
System.Text.StringBuilder sbMessage = new System.Text.StringBuilder ("John");
sbMessage.Append("|");
sbMessage.Append(strSender);
sbMessage.Append("|");
sbMessage.Append(strReceiver);
sbMessage.Append("|");
sbMessage.Append((int)cmdMessageCommand);
sbMessage.Append("|");
sbMessage.Append(strMessageDetail);
sbMessage.Append("|");
return System.Text.Encoding.ASCII.GetBytes(sbMessage.ToString());
}
...


The Server Project


I created a SocketServer that calls the TCPListener.Start() method

IPEndPoint endPoint = new IPEndPoint (ipaAddress, iPort);
listener = new TcpListener (endPoint);
listener.Start();


Upon calling Listen, a new thread will be created that will listen for incoming clients

thrListenForClients = new Thread(new ThreadStart(ListenForClients));
thrListenForClients.Start();


The ListenForClients method will wait for connections and will assign the incoming socket to a new Client instance.

Client acceptClient = new Client();
acceptClient.Socket = listener.AcceptTcpClient();
listenForMessageDelegate = new ListenForMessageDelegate (ListenForMessages);
listenForMessageDelegate.BeginInvoke(acceptClient, new AsyncCallback(ListenForMessagesCallback), "Completed");


The Client, by the way is a class that contains a TCPClient, so we can keep track of our connections

public class Client {
string strName;
TcpClient tcpClient;
public Client()
{
}
public string Name
{
get{return strName;}
set{ this.strName = value;}
}
public TcpClient Socket
{
get{return tcpClient;}
set{ this.tcpClient = value;}
}
public void SendMessage (Message sendMessage)
{
NetworkStream stream = tcpClient.GetStream();
stream.Write(sendMessage.GetRawMessage() , 0, sendMessage.GetRawMessage().Length);
}
}


Our server is now ready to listen for incoming messages. To do this, we pass the client socket that we received, then make a loop. We use a NetworkStream to read the message

NetworkStream stream = client.Socket.GetStream();
byte [] bytAcceptMessage = new byte [1024];
stream.Read(bytAcceptMessage, 0, bytAcceptMessage.Length);
Message message = new ChatLibrary.Message(bytAcceptMessage);


Once we receive the message, we can do anything that we want

txtStatus.Text += "rn" + strDisplayMessageType + strWriteText.TrimStart(new char[]{'r','n'});


My SocketServer makes use of a few events that makes coding a little easier

public event ClientConnectedEventHandler ClientConnected;
public event ClientDisconnectingEventHandler ClientDisconnecting;
public event MessageReceivedEventHandler MessageReceived;


In my ServerForm codes, what I did was I kept a copy of each connected Client in a ClientCollection that inherits from System.Collections.CollectionBase. With this, I can iterate through the Clients.

The Client Project


The Client does basically the same thing. I created a ClientSocket that will create a TCPListener and call Connect()

IPEndPoint serverEndpoint = new IPEndPoint (ipaAddress , iPort);
tcpClient = new TcpClient ();
tcpClient.Connect(serverEndpoint);
thrListenForMessages = new Thread (new ThreadStart(ListenForMessages));
thrListenForMessages.Start();


What ListenForMessages will do is to loop with NetworkStream.Read()

stream = tcpClient.GetStream();
byte [] bytRawMessage = new byte [1024];
stream.Read(bytRawMessage, 0, bytRawMessage.Length);
ChatMessage receivedMessage = new ChatLibrary.Message (bytRawMessage);


Then we do the same process, create a Message using the received bytes.

Again, my goal is to create a YM/MSN - looking Instant Messenger, so I made two UI forms. The MessengerForm and the ClientWindow. The MessengerForm is the class that instantiates the ClientSocket and receives the messages. upon receiving a message, it calls the MessengerWindow that should display the text.

Note that I didn't do a regular instantiation. I called Invoke to be able to make my controls thread safe

this.Invoke(createNewClientDelegate, new object []{receivedMessage});


History


June 2006 : Initial Version



License


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors may to use can be found here

About the Author







massivegas


John lives in the Philippines with his family, working as a programmer. He used to program VB6 but is now... ummm... trying to learn C# .Net.









Occupation: Web Developer
Location: Philippines Philippines