📄 mtsrv1.cpp
字号:
/*---------------------------------------------------------------------------
Author: Fran鏾is PIETTE
Description: This little application shows how to use the TWSocket in a
multithreaded application. It is a very basic telnet werver.
Each time a client connect to the server, he receive an "hello"
message. Then every character sent is echoed back to the client.
There are two units is this application: one for the main
server code, and one for the client thread.
Each time a client connect to the server, a new TWSocket is
created and a new thread is launched to handle the client
work. When the client disconnect, the TWSocket and the thread
are destroyed.
To see this demo working on your computer, start the demo then
start several copies of the TELNET client program (the one which
comes with Windows 95 is perfect). Then using each telnet, connect
to 127.0.0.1. You'll see a new connection in the list box. You
must receive the "hello" message and see each character as you
type them. You can use the Disconnect button from the application
or from the telnet client to see what happends (the connection
should be closed).
Creation: September 25, 1997 (from Delphi version dated September 21, 1997)
Version: 1.01
EMail: francois.piette@swing.be francois.piette@pophost.eunet.be
francois.piette@rtfm.be http://www.rtfm.be/fpiette
Support: Use the mailing list twsocket@rtfm.be See website for details.
Legal issues: Copyright (C) 1997-2000 by Fran鏾is PIETTE
<francois.piette@pophost.eunet.be>
This software is provided 'as-is', without any express or
implied warranty. In no event will the author be held liable
for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it
and redistribute it freely, subject to the following
restrictions:
1. The origin of this software must not be misrepresented,
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but is
not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
Updates:
Nov 15, 1997 Corrected a bug in the disconnect method which crashed the server
when you tried to disconnect the second or later client.
---------------------------------------------------------------------------*/
#include <vcl\vcl.h>
#pragma hdrstop
#include "mtsrv1.h"
#include "mtsrv2.h"
//---------------------------------------------------------------------------
#pragma link "WSocket"
#pragma resource "*.dfm"
TServerForm *ServerForm;
//---------------------------------------------------------------------------
// Convert an hexdigit to an integer
int xdigit(char Ch)
{
if ((Ch >= '0') && (Ch <= '9'))
return(Ch - '0');
else
return((Ch & 15) + 9);
}
//---------------------------------------------------------------------------
// Check if a character is a valid hex digit
int isxDigit(char Ch)
{
return(((Ch >= '0') && (Ch <= '9')) ||
((Ch >= 'a') && (Ch <= 'z')) ||
((Ch >= 'A') && (Ch <= 'Z')));
}
//---------------------------------------------------------------------------
// Convert the ascii representation of a hex number to an integer
int htoi(char *Value)
{
int i;
int Result;
Result = 0;
i = 0;
while ((Value[i] != 0) && (Value[i] == ' '))
i++;
while ((Value[i] != 0) && isxDigit(Value[i])) {
Result = Result * 16 + xdigit(Value[i]);
i++;
}
return(Result);
}
//---------------------------------------------------------------------------
__fastcall TServerForm::TServerForm(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TServerForm::ServerWSocketSessionAvailable(TObject *Sender,
WORD Error)
{
TClientThread *ClientThread;
// Create a new thread to handle client request
ClientThread = new TClientThread(ServerWSocket->Accept());
// Assign the thread's OnTerminate event
ClientThread->OnTerminate = ClientThreadTerminate;
// Add the thread to the listbox which is our client list
ClientListBox->Items->Add(IntToHex(Integer(ClientThread), 8));
// Then start the client thread work
// because it was created in the blocked state
ClientThread->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TServerForm::FormShow(TObject *Sender)
{
static BOOL FirstTime = TRUE;
if (FirstTime) {
FirstTime = FALSE;
#if (WSocketVersion < 202)
#error "Please update your wsocket.pas to version 2.02 or later. "
#error "Free download at http://www.rtfm.be/fpiette/indexuk.htm"
#error "EMail at francois.piette@pophost.eunet.be"
#endif
ServerWSocket->Proto = "tcp"; // We use a TCP connection
ServerWSocket->Port = "telnet"; // We wants to use telnet
ServerWSocket->Addr = "0.0.0.0"; // We accept any client
ServerWSocket->Listen(); // Start server accepting
}
}
//---------------------------------------------------------------------------
// This event is generated when the user clicks on the 'Disconnect' button
// when he wants to disconnect the selected client in the listbox.
void __fastcall TServerForm::DisconnectButtonClick(TObject *Sender)
{
TClientThread *ClientThread;
AnsiString Buf;
// No selected item, nothing to do
if (ClientListBox->ItemIndex < 0)
return;
// Extract the ClientThread pointer from the list box
Buf = ClientListBox->Items->Strings[ClientListBox->ItemIndex];
ClientThread = (TClientThread *)htoi(Buf.c_str());
// Call ClientThread.Release which will stop the thread
// In consequence, the OnTerminate event will be generated
ClientThread->Release();
}
//---------------------------------------------------------------------------
// This event handler is called when one of the client thread terminate
// We will find this thread in our listbox, remove it and destroy the
// TWSocket object use by the corresponding client.
void __fastcall TServerForm::ClientThreadTerminate(TObject *Sender)
{
TClientThread *ClientThread;
AnsiString Buf;
int Index;
// A thread has been terminated, remove it from our list and destroy
// the ClientWSocket we passed to the thread.
Index = 0;
while (Index < ClientListBox->Items->Count) {
Buf = ClientListBox->Items->Strings[Index];
ClientThread = (TClientThread *)htoi(Buf.c_str());
if (ClientThread == (TClientThread *)Sender) {
// Remove the client from our listbox
ClientListBox->Items->Delete(Index);
break;
}
Index++;
}
}
//---------------------------------------------------------------------------
// This procedure scan the listbox and halt every ClientThread
void __fastcall TServerForm::DisconnectAll()
{
TClientThread *ClientThread;
AnsiString Buf;
while (ClientListBox->Items->Count > 0) {
Buf = ClientListBox->Items[0].Text;
ClientThread = (TClientThread *)htoi(Buf.c_str());
ClientThread->Release();
Application->ProcessMessages();
}
}
//---------------------------------------------------------------------------
void __fastcall TServerForm::QuitButtonClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TServerForm::DisconnectAllButtonClick(TObject *Sender)
{
DisconnectAll();
}
//---------------------------------------------------------------------------
void __fastcall TServerForm::FormCloseQuery(TObject *Sender, bool &CanClose)
{
DisconnectAll();
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -