Introduction
This article demonstrates the technique of creating a chat system. The article contains a chat server and a chat client, each performs different tasks and cannot be used interchangeably. Both client and server use Windows sockets for the purpose of connecting and sending lines of text between themselves. You can use the server and client either on your machine or over a private LAN or network to chat.
NOTE: I do not have access to either a LAN or network, hence this software was only tested in "local loop" on my machine, anyone testing the software over a network can please send the test results through E-Mail to me.
How to use
Preparing to use ChatServer & ChatClient
- Download the
ChatServer
& ChatClient
source code
- Unzip
ChatServer
& ChatClient
source code
- Start Visual Studio
- Build the
ChatServer
& ChatClient
executables
- Exit Visual Studio
To use the ChatServer
and ChatClient
on your machine in what is know as "Local Loop", do the following:
Starting ChatServer
- Start
ChatServer
(executable is in ChatServer\Debug folder)
- Keep the port no. 0 and click Ok (note: if you change the port no. the same no. must be used when connecting through
ChatClient
)
- Port no. can be between 0 to 1499 (this is useful in cases where the port no. is in use by another application on the server system
- Note: Even though the port no. input is 0, it is in reality 1500 + x (x stands for the port no. input by you, 0 in this case)
Starting ChatClient
- Start
ChatClient
(executable is in ChatClient\Debug folder)
- From the menu, select Connection->Connect (or click on the Connect button)
- Logon form will be displayed
- In the server box type 127.0.0.1
- In the nickname box type any name (should be different for each invocation of
ChatClient
)
- In the port no. box type 0 (remember we had started the
ChatServer
with 0 as port no.)
- Click Ok
- Repeat steps 1 thru 7 above to start another
ChatClient
but with a different nickname. You can start as many ChatClient
s as you want, restricted by available memory.
- Chat to your hearts content, with yourself of course.
To use ChatServer
and ChatClient
on a network do the following, carry out the steps in the "Preparing to use ChatServer & ChatClient" above.
- Copy
ChatServer
executable on a server system
- Copy
ChatClient
executables on machines from where you want users to chat
- Start
ChatServer
on the server system, refer the "Starting ChatServer" section above
- Start
ChatClient
on the machines where the ChatClient
s were copied, refer the "Starting ChatClient" section above, but remember, in the server box on the logon form, you have to type the name or IP address of the server system on which the ChatServer
is running (not 127.0.0.1) and port no. as applicable
Caution
If you copy ChatServer
and ChatClient
executables on machines that do not have Visual Studio setup, the executables may not run since MFC is not installed by default on the Windows operating system.
If the installable versions of ChatServer
and ChatClient
are available for download in the download section at the top, you can install both on any machine running Windows 9x /Windows 2000 / Windows XP, since the Installable versions have MFC included.
I may not upload the installable versions at present because of their huge size (1.2Mb each) and to be very frank I cannot afford it at present, maybe over a period of time, if there is demand for the same.
What's missing
- No colored text for chatting
- No variable fonts for chatting
- Single chat room
- No threads used in the source
Maybe in a later version the above could be incorporated, presently under testing.
Note for developers
Most important code for both the server and client is in the classes CChatServerDoc
and CChatClientDoc
, you would well concentrate on these two classes.
A CObject
class named CMsg
is used in both server and client to send and receive messages back and forth, which are then unassembled by the receiver (server or client). CMsg
class has the following members:
Code
(to indicate the type of message)
m_strText
(message text)
m_bClose
(sent when the client is disconnecting or shutting down)
Following is a list of codes sent by both server and client (you can have your own codes as the need maybe):
#define JOINING_CHAT 1
#define LEAVING_CHAT 2
#define SENDING_CHATTERS_LIST 3
#define SENDING_NICKNAME 4
#define NORMAL_MESSAGE 5
#define DUPLICATE_NICKNAME 6
How it works
After you start the server by inputting port no. and clicking Ok, a socket is created for listening for incoming connect request, using the following code in the member function OnNewDocument()
m_pSocket = new CListeningSocket(this);
if (m_pSocket->Create(Dialog.m_nPort+1500))
{
if (m_pSocket->Listen())
return TRUE;
}
When a new connect request is received from a client, the member function OnAccept
in the class CListeningSocket
is notified by the system. OnAccept
then calls ProcessPendingAccept
function in class CChatServerDoc
as show below:
void CListeningSocket::OnAccept(int nErrorCode)
{
CSocket::OnAccept(nErrorCode);
m_pDoc->ProcessPendingAccept();
}
In the ProcessPendingAccept
function, a new socket (CClientSocket
) is created for the new client and the created socket is added to the pointer list CPtrList
, which is a kind of array. We use the pointer list all throughout the program to retrieve the socket for sending or receiving messages. The system then reads the incoming message in the member function OnReceive
in the CClientSocket
which in turn calls ProcessPendingRead
sending to it the client socket, which sends the message, as shown below:
void CClientSocket::OnReceive(int nErrorCode)
{
CSocket::OnReceive(nErrorCode);
m_pDoc->ProcessPendingRead(this);
}
Inside ProcessPendingRead
the CMsg object
sent by the client is unassembled and based on Code
of the message, action is taken as appropriate.
When a client disconnects or exits by selecting from menu, File->Exit, a message is sent to the server with m_bClose
set to TRUE
. Server receives the message and closes the client socket as shown below:
void CChatServerDoc::CloseSocket(CClientSocket* pSocket)
{
pSocket->Close();
POSITION pos,temp;
for(pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
temp = pos;
CClientSocket* pSock =
(CClientSocket*)m_connectionList.GetNext(pos);
if (pSock == pSocket)
{
m_connectionList.RemoveAt(temp);
break;
}
}
UpdateConnections();
delete pSocket;
if(m_connectionList.GetCount() == 0)
m_msgList.RemoveAll();
}
If you exit the server by selecting from the menu, File->Exit, and if there are clients connected, all the clients are notified by the server that it has shut down and all the CClientSocket(s)
are closed. This also prevents the clients from crashing. Following is the code which carries out the task of closing the client sockets.
void CChatServerDoc::DeleteContents()
{
if(m_pSocket == (CListeningSocket*)NULL)
return;
delete m_pSocket;
m_pSocket = NULL;
CString temp;
if (temp.LoadString(IDS_SERVERSHUTDOWN))
m_msgList.AddTail(temp);
while(!m_connectionList.IsEmpty())
{
CClientSocket* pSocket =
(CClientSocket*)m_connectionList.RemoveHead();
CMsg* pMsg = AssembleMsg(pSocket , NORMAL_MESSAGE);
pMsg->m_bClose = TRUE;
SendMsg(pSocket, pMsg);
if (!pSocket->IsAborted())
{
pSocket->ShutDown();
BYTE Buffer[50];
while (pSocket->Receive(Buffer,50) > 0);
delete pSocket;
}
}
m_msgList.RemoveAll();
if (!m_viewList.IsEmpty())
Message("");
CDocument::DeleteContents();
}
Have fun, chat to your heart's content, but don't blame me. I developed this by modifying MSDN Sample Chatter & Chatsvr for fun sake.