티스토리 뷰
Application/C#
A simple Multi-Threaded Server Client Instant Messenger Application
알 수 없는 사용자 2008. 1. 28. 21:23<!-- 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
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());
}
...
IPEndPoint endPoint = new IPEndPoint (ipaAddress, iPort);
listener = new TcpListener (endPoint);
listener.Start();
thrListenForClients = new Thread(new ThreadStart(ListenForClients));
thrListenForClients.Start();
Client acceptClient = new Client();
acceptClient.Socket = listener.AcceptTcpClient();
listenForMessageDelegate = new ListenForMessageDelegate (ListenForMessages);
listenForMessageDelegate.BeginInvoke(acceptClient, new AsyncCallback(ListenForMessagesCallback), "Completed");
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);
}
}
NetworkStream stream = client.Socket.GetStream();
byte [] bytAcceptMessage = new byte [1024];
stream.Read(bytAcceptMessage, 0, bytAcceptMessage.Length);
Message message = new ChatLibrary.Message(bytAcceptMessage);
txtStatus.Text += "rn" + strDisplayMessageType + strWriteText.TrimStart(new char[]{'r','n'});
public event ClientConnectedEventHandler ClientConnected;
public event ClientDisconnectingEventHandler ClientDisconnecting;
public event MessageReceivedEventHandler MessageReceived;
IPEndPoint serverEndpoint = new IPEndPoint (ipaAddress , iPort);
tcpClient = new TcpClient ();
tcpClient.Connect(serverEndpoint);
thrListenForMessages = new Thread (new ThreadStart(ListenForMessages));
thrListenForMessages.Start();
stream = tcpClient.GetStream();
byte [] bytRawMessage = new byte [1024];
stream.Read(bytRawMessage, 0, bytRawMessage.Length);
ChatMessage receivedMessage = new ChatLibrary.Message (bytRawMessage);
this.Invoke(createNewClientDelegate, new object []{receivedMessage});
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.
|
'Application > C#' 카테고리의 다른 글
An Asynchronous Socket Server and Client (0) | 2008.01.28 |
---|---|
Using Updater Block (0) | 2008.01.28 |
MyDownloader: A Multi-thread C# Segmented Download Manager (15) | 2008.01.28 |
폼 새창 로드시 포커스 문제? (0) | 2008.01.28 |
Playing AVI Files using DirectX 9 with C# and .NET (29) | 2008.01.28 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- Tech News
- Military
- C#
- wallpaper
- 나비효과
- Mabinogi
- WDB
- Embedded System
- USB Lecture
- 짤방 및 아이콘
- Life News
- 막장로그
- network
- Network Inspector
- Web Programming
- 야마꼬툰
- medical
- win32
- cartoon
- humor
- Reverse Engineering
- console
- Assembly
- Information Processor
- Linux
- diary
- Battle
- 프리랜서로 살아남는 법
- 3D Engine
- BadCode
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함