用C++ Builder中的TServerSocket,TClientSocket來寫網路通訊程式 (轉)
本文主要介紹如何在C++ Builder中用TServerSocket,TClientSocket來寫一個間短包,傳輸的,這個程式可以支援:1.上的傳輸。2.區域網與公網的傳輸(雙向傳輸),在第二篇文章中我將用socket 寫一個客戶端和,功能和本文中的功能一樣。使用通訊TCP,這裡的客戶端和伺服器使用的都是阻塞---多執行緒。
Client:
.h File
class ClientThread : public TThread
{
private:
AnsiString File;
TClientSocket* ClientSocket;
TWinSocketStream* WskStream;
protected:
void __fastcall Execute();
public:
__fastcall ClientThread(AnsiString IPAddr,
Port, AnsiString file);
};
.cpp File
void __fastcall ClientThread::Execute()
{
Text or SendFile
UINT TimeOut=60000;
char buf[4096];
IPAddress[32];
(IPAddress);//IPAddress
WskStream = new TWinSocketStream(ClientSocket->Socket, TimeOut);
if(Form1->CheckBox1->Checked)//Detene whether to send short package or send file.
{
String S=Form1->TxtEdit->Text;
int TxtLen=Form1->TxtEdit->Text.Length();
strncpy(buf,S.c_str(),TxtLen);
ClientSocket->Active=true;
>Write("TEXT",5);//Send Text Flag
>Write(IPAddress,32);//Send Address
WskStream->Write(buf,TxtLen);//Send Text String
WskStream->Write(buf,TxtLen);
if(WskStream->WaitForData(TimeOut))
{
buf[0]='';
[0]='';
[0]='';
>Read(FlagBuf,5);
>Read(IPAddress,32);
int nSize=0;
nSize=WskStream->Read(buf,TxtLen);
buf[nSize]='';
if(!StrPas(buf).IsEmpty())
{
SaveLog("Received a text!");
("Client:"+StrPas(IPAddress)+"
Start Time:"+DateTimeToStr(Now()));
SaveLog("Text Content:"+StrPas(buf));
FLASHWINFO FSHINFO;
::ZeroMemory(&FSHINFO,sizeof(FLASHWINFO));
FSHINFO.cbSize=sizeof(FLASHWINFO);
FSHINFO.hwnd=Application->Handle;
FSHINFO.dwFlags=FLASHW_TRAY|FLASHW_CAPTION;
FSHINFO.uCount=10;
FSHINFO.dwTimeout=200;
::FlashWindowEx(&FSHINFO);
Form1->RecEdit->Lines->Add("Received Length:"+String(nSize));
Form1->RecEdit->Lines->Add("Received:"+StrPas(buf));
("Client:"+StrPas(IPAddress)+"
End Time:"+DateTimeToStr(Now()));
}
}
}
else
{
int nLen;
int hFile;
int nSize;
char Path[255];//Path Buffer
char FileName[255];//FileName Buffer;
char FileExt[5];//Extension Buffer
char FlagBuf[5];
static int num=0;
AnsiString ileName=ExtractFileName(File);
for(int k=sFileName.Length();k>0;k--)
{
if(sFileName.SubString(k,1)==".")
{
sFileName=sFileName.SubString(1,k-1);
break;
}
}
AnsiString sPath=ExtractFilePath(File);
AnsiString sExtension=ExtractFileExt(File);
strcpy(FileName,sFileName.c_str());//FileName
strcpy(Path,sPath.c_str());
strcpy(FileExt,sExtension.c_str());
try {
hFile = -1;
ClientSocket->Active = true;
hFile = FileOpen(File, fmOpenRead);
if (hFile != -1) {
nSize = GetFileSize((HANDLE)
hFile, NULL);
the Flag
WskStream->Write("FILE",5);
the name of directory
WskStream->Write(Path,255);
the filename
WskStream->Write(FileName,255);
the extension of file
WskStream->Write(FileExt,5);
client's IP addresss
WskStream->Write(IPAddress,32);
the length
WskStream->Write(&nSize, 4);
the data
for(; nSize>0; nSize-=nLen) {
nLen = min((int)sizeof(
buf), nSize);
nLen = FileRead(hFile, buf,
nLen);
if (nLen<=0) break;
WskStream->Write(buf, nLen);
}
}
FileClose(hFile);//Send Completely
is beginning to read data
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(FlagBuf,5);
}
if(WskStream->WaitForData(TimeOut))//Obtain the directory's name
{
WskStream->Read(Path,255);
}
the directory obtained from client doesnot exist,the create it
if(!DirectoryExists(StrPas(Path)))
{
CreateDir(StrPas(Path));
}
the FileName
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(FileName,255);
}
the extension
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(FileExt,5);
}
the client's IPAddress
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(IPAddress,32);
}
AnsiString S=StrPas(Path)+StrPas(FileName)+StrPas(FileExt);
buf[0]='';
strcpy(buf,S.c_str());
while(1) {
if (FileExists(buf)) {
S=StrPas(Path)+StrPas(FileName)+"%03d"+StrPas(FileExt);
wsprintf(buf, S.c_str(),
num);
num++;
Susscessfully
} else break;
}
hFile = FileCreate(buf);
if (hFile==-1)
{
Application->MessageBox("Failed to create file!","Error",MB_OK+MB_ICONERROR);
ClientSocket->Active=false;
delete WskStream;
Terminate();
return;
}
SaveLog("Received a file:"+StrPas(buf));
SaveLog("Client:"+StrPas(IPAddress)+"
Start Time:"+DateTimeToStr(Now()));
try {
DWORD dwTick = GetTickCount();
the length
if (WskStream->WaitForData(
TimeOut)) {
nLen = WskStream->Read(
&nSize, 4);
if (nLen!=4) nSize = 0;
}
else
nSize = 0;
data
for(; nSize>0 && !Terminated;
nSize-=nLen) {
if (!WskStream->WaitForData(
5000)) {
if (GetTickCount()-dwTick
::MessageBox(NULL,"Timeout,the thread has been terminated!","Error",MB_OK|MB_ICONERROR);
ClientSocket->Active=false;
break;
}
nLen = WskStream->Read(buf,
sizeof(buf));
dwTick = GetTickCount();
if (nLen <= 0) {
Error
ClientSocket->Active=false;
::MessageBox(NULL,"Read Error,the thread has been terminated!","Error",MB_OK|MB_ICONERROR);
break;
}
the data
FileWrite(hFile, buf, nLen);
}
Form1->RecEdit->Lines->Add("You got a file from server,which was saved in "+StrPas(Path));
SaveLog("Client:"+StrPas(IPAddress)+"
End Time:"+DateTimeToStr(Now()));
FLASHWINFO FSHINFO;
::ZeroMemory(&FSHINFO,sizeof(FLASHWINFO));
FSHINFO.cbSize=sizeof(FLASHWINFO);
FSHINFO.hwnd=Application->Handle;
FSHINFO.dwFlags=FLASHW_TRAY|FLASHW_CAPTION;
FSHINFO.uCount=10;
FSHINFO.dwTimeout=200;
::FlashWindowEx(&FSHINFO);
FileClose(hFile);
}
catch(Exception& e) {
ClientSocket->Active=false;
MessageBox(0, e.Message.c_str(),
"Error", MB_ICONERROR);
}
}
catch(Exception& e) {
ClientSocket->Active=false;
::MessageBox(0, e.Message.c_str(),
"Error", MB_OK|MB_ICONERROR);
}
FileClose(hFile);
}
delete WskStream; // delete ClientSocket;
}
to send package
void __fastcall TForm1::Button1Click(T *Sender)
{
int Port;
AnsiString Addr;
Addr = IPAddr->Text.Trim();
if (Addr.IsEmpty()) {
IPAddr->SetFocus();
Application->MessageBox("Please enter the client's address!","Warning",MB_OK|MB_ICONWARNING);
return;
}
try {
Port = ClientPort->Text.ToInt();
}
catch(Exception& e) {
ShowMessage(e.Message);
ClientPort->SetFocus(); return;
}
if(CheckBox1->Checked) Text
{
if(TxtEdit->Text.IsEmpty())
{
::MessageBox(0,"Please enter the text string which you want to send!","Error",MB_OK+MB_ICONERROR);
return;
}
new ClientThread(Addr,Port,"");
}
else File
{
if (OpenDialog1->Execute())
new ClientThread(Addr, Port,
OpenDialog1->FileName); to send data
}
}
Server:
.h File
Comments:
design-time,please place a TServerSocket Component on your foand set its clientype to stThrealocking.
Thread Class
Server Can not only receives the packages coming from Clients,but also deliver the package to the clients after
processing upon the package.
class SrvThread : public TServerClientThread
{
private:
UINT FTimeOut;
TWinSocketStream* WskStream;
TThread *pThread;
protected:
void __fastcall ClientExecute();
public:
__fastcall SrvThread(TServerClientWinSocket*);
__property UINT TimeOut = { read=FTimeOut, write=FTimeOut };
};
void __fastcall SrvThread::ClientExecute()
{
TimeOut = 60000; Seconds
WskStream = new TWinSocketStream(ClientSocket, TimeOut);
Text or File
char FlagBuf[5];
char buf[4096];
char IPAddress[32];
SMS[0]='';
RecIPAddr[0]='';
if(WskStream->WaitForData(TimeOut)) Flag:File or Text
{
WskStream->Read(FlagBuf,5);
}
the flag received from clients
strcpy(Flag,FlagBuf);
if(StrPas(FlagBuf)=="TEXT")
{
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(IPAddress,32);
}
the client's IPAddress
strcpy(RecIPAddr,IPAddress);
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(buf,4096);
}
the short message received from clients
strcpy(SMS,buf);
SaveLog("Received a text!");
SaveLog("Client:"+StrPas(IPAddress)+"
Start Time:"+DateTimeToStr(Now()));
SaveLog("Text Content:"+StrPas(SMS));
SaveLog("Client:"+StrPas(IPAddress)+"
End Time:"+DateTimeToStr(Now()));
Form1->Memo1->Lines->Add("Text Content:"+StrPas(buf));
FLASHWINFO FSHINFO;
::ZeroMemory(&FSHINFO,sizeof(FLASHWINFO));
FSHINFO.cbSize=sizeof(FLASHWINFO);
FSHINFO.hwnd=Application->Handle;
FSHINFO.dwFlags=FLASHW_TRAY|FLASHW_CAPTION;
FSHINFO.uCount=10;
FSHINFO.dwTimeout=200;
::FlashWindowEx(&FSHINFO);
if(Form1->adv->Checked)//Automatically Deliver To Client
{
if(StrPas(Flag).IsEmpty() || StrPas(RecIPAddr).IsEmpty() || StrPas(SMS).IsEmpty())
{
Application->MessageBox("You can't deliver because no data are received!","Error",MB_OK+MB_ICONERROR);
return;
}
WskStream->Write(FlagBuf,5);
WskStream->Write(Form1->ComboBox1->Text.c_str(),32);
WskStream->Write(SMS,4096);
::Sleep(500);//Delay for 500ms
ClientSocket->Close();
}
if(Form1->spt->Checked)//Automatically deliver to serial port on local computer
{
StrCat(SMS,FlagBuf);
StrCat(SMS,Form1->ComboBox1->Text.c_str());
// SaveLog("Write Serial Port "+Form1->Port);
// SaveLog("Start Time:"+DateTimeToStr(Now()));
// SaveLog("End Time:"+DateTimeToStr(Now()));
pThread=new TWriteCommThread(Form1->Port,Form1->BaudRate,(void*)buf,1000);
pThread->Terminate();
}
}
else
{
if(StrPas(FlagBuf).Pos("GET"))
{
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(buf,4096);
}
the flag to Flag
strcpy(Flag,"GPRS");
the frame to SMS
strcpy(SMS,buf);
the destination IP
strcpy(RecIPAddr,"127.0.0.1");
SaveLog("Received a package from GPRS");
SaveLog("Start Time:"+DateTimeToStr(Now()));
SaveLog(StrPas(FlagBuf)+StrPas(buf));
SaveLog("End Time:"+DateTimeToStr(Now()));
Form1->Memo1->Lines->Add(StrPas(FlagBuf)+StrPas(buf));
FLASHWINFO FSHINFO;
::ZeroMemory(&FSHINFO,sizeof(FLASHWINFO));
FSHINFO.cbSize=sizeof(FLASHWINFO);
FSHINFO.hwnd=Application->Handle;
FSHINFO.dwFlags=FLASHW_TRAY|FLASHW_CAPTION;
FSHINFO.uCount=10;
FSHINFO.dwTimeout=200;
::FlashWindowEx(&FSHINFO);
if(Form1->adv->Checked)
{
if(StrPas(Flag).IsEmpty() || StrPas(RecIPAddr).IsEmpty() || StrPas(SMS).IsEmpty())
{
Application->MessageBox("You can't deliver because no data are received!","Error",MB_OK+MB_ICONERROR);
return;
}
WskStream->Write(FlagBuf,5);
WskStream->Write(Form1->ComboBox1->Text.c_str(),32);
WskStream->Write(SMS,4096);
::Sleep(500);//ms
ClientSocket->Close();
}
if(Form1->spt->Checked) deliver to serial port on local computer
{
StrCat(SMS,FlagBuf);
StrCat(SMS,Form1->ComboBox1->Text.c_str());
("Write Serial Port "+Form1->Port);
("Start Time:"+DateTimeToStr(Now()));
("End Time:"+DateTimeToStr(Now()));
pThread=new TWriteCommThread(Form1->Port,Form1->BaudRate,(void*)SMS,4096);
pThread->Terminate();
}
}
else
{
int nLen;
int nSize;
int hFile;
char Path[255];
char FileName[255];
char FileExt[5];
static int num=0;
the directory's name
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(Path,255);
}
the directory obtained from client doesnot exist,the create it
if(!DirectoryExists(StrPas(Path)))
{
CreateDir(StrPas(Path));
}
the FileName
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(FileName,255);
}
the extension
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(FileExt,5);
}
the client's IPAddress
if(WskStream->WaitForData(TimeOut))
{
WskStream->Read(IPAddress,32);
}
the client's IPAddress
strcpy(RecIPAddr,IPAddress);
AnsiString S=StrPas(Path)+StrPas(FileName)+StrPas(FileExt);
strcpy(buf,S.c_str());
while(1) {
if (FileExists(buf)) {
S=StrPas(Path)+StrPas(FileName)+"%03d"+StrPas(FileExt);
wsprintf(buf, S.c_str(),
num);
num++;
Susscessfully
} else break;
}
hFile = FileCreate(buf);
if (hFile==-1)
{
Application->MessageBox("Failed to create file on server!","Error",MB_OK+MB_ICONERROR);
delete WskStream;
Terminate();
return;
}
the filename received from clients
strncpy(RecFile,buf,255);
SaveLog("Received a file:"+StrPas(buf));
SaveLog("Client:"+StrPas(IPAddress)+"
Start Time:"+DateTimeToStr(Now()));
try {
DWORD dwTick = GetTickCount();
the length
if (WskStream->WaitForData(
TimeOut)) {
nLen = WskStream->Read(
&nSize, 4);
if (nLen!=4) nSize = 0;
}
else
nSize = 0;
data
for(; nSize>0 && !Terminated;
nSize-=nLen) {
if (!WskStream->WaitForData(
5000)) {
if (GetTickCount()-dwTick
::MessageBox(NULL,"Timeout,the thread has been terminated!","Error",MB_OK|MB_ICONERROR);
break;
}
nLen = WskStream->Read(buf,
sizeof(buf));
dwTick = GetTickCount();
if (nLen <= 0) {
Error
::MessageBox(NULL,"Read Error,the thread has been terminated!","Error",MB_OK|MB_ICONERROR);
break;
}
the data
FileWrite(hFile, buf, nLen);
}
SaveLog("Client:"+StrPas(IPAddress)+"
End Time:"+DateTimeToStr(Now()));
Form1->Memo1->Lines->Add("You got a file received from client,which was saved in "+StrPas(Path));
>MessageBox("Server has successfully received the data !","Notification",MB_OK+MB_ICONINFORMATION);
FLASHWINFO FSHINFO;
::ZeroMemory(&FSHINFO,sizeof(FLASHWINFO));
FSHINFO.cbSize=sizeof(FLASHWINFO);
FSHINFO.hwnd=Application->Handle;
FSHINFO.dwFlags=FLASHW_TRAY|FLASHW_CAPTION;
FSHINFO.uCount=10;
FSHINFO.dwTimeout=200;
::FlashWindowEx(&FSHINFO);
FileClose(hFile);//Read Completely
if(Form1->adv->Checked)//Automatically Deliver
{
if(StrPas(Flag).IsEmpty() || StrPas(RecIPAddr).IsEmpty())
{
Application->MessageBox("You can't deliver because no data are received!","Error",MB_OK+MB_ICONERROR);
return;
}
Data
try
{
buf[0]='';
hFile = -1;
hFile = FileOpen(StrPas(RecFile), fmOpenRead);
if (hFile != -1) {
nSize = GetFileSize((HANDLE)
hFile, NULL);
the Flag
WskStream->Write("FILE",5);
the name of directory
WskStream->Write(Path,255);
the filename
WskStream->Write(FileName,255);
the extension of file
WskStream->Write(FileExt,5);
client's IP addresss
WskStream->Write(Form1->ComboBox1->Text.c_str(),32);
the length
WskStream->Write(&nSize, 4);
the data
for(; nSize>0; nSize-=nLen) {
nLen = min((int)sizeof(
buf), nSize);
nLen = FileRead(hFile, buf,
nLen);
if (nLen<=0) break;
WskStream->Write(buf, nLen);
}
}
}
catch(Exception& e) {
ClientSocket->Close();
::MessageBox(0, e.Message.c_str(),
"Error", MB_OK|MB_ICONERROR);
}
FileClose(hFile);
}//if
}//catch
catch(Exception& e) {
ClientSocket->Close();
::MessageBox(0, e.Message.c_str(),
"Error", MB_ICONERROR);
}
}
}
delete WskStream;
WskStream=NULL;
::Sleep(100);
}
ServerSocket's OnGetThread event to new a thread to communication with the requested client
void __fastcall TForm1::ServerSocket1GetThread(TObject *Sender,
TServerClientWinSocket *ClientSocket,
TServerClientThread *&SocketThread)
{
SocketThread = new SrvThread(ClientSocket);
}
metioned-written codes is used to test a hardware.It can be run correctly.As many different applications,so you only reference it and could not be copy completely.It is important to know the principle of TServerSocket,TClientSocket and VCL wraps the socket api.This article only provs the support of TCP protocol.The next article I will write will TCP and UDP protocol,please pay your attention for it.At this time,I would like to thank jishi() and Raptor for their help.Thanks for browsing it.I am can be contacted via :kingcaiyao@163.com">:kingcaiyao@163.com
以上程式可以實現伺服器與客戶端之間的雙向通訊,只用一個埠,其工作原理類似於IE,由客戶端主動發起連線,伺服器端在收到資料包後進行處理,然後根據已建立起的鏈路,再將資料回寫到客戶端。在同處在兩臺區域網的機器上以及一臺處於局域,而另一臺處於公網的機器上都測試透過。還有我從去年起開始接觸網路,中間得到jishiping,Raptor的指點和幫助,在此再次感謝他們。
補充說明一點,我將程式碼經過Notepad編輯後copy到這裡的時,發現所有的註釋部分都加了一個file:,因此當你看到file:字首時,那就是註釋,並非程式碼,特此宣告
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-960511/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在C++ Builder中用socket api來寫網路通訊程式(同時支援TCP和UDP協議) (轉)C++UIAPITCPUDP協議
- 在C++ Builder中用socket api來寫網路通訊程式(同時支援TCP和UDP協議)C++UIAPITCPUDP協議
- 用 C++Builder 編寫 Tray 程式 (轉)C++UI
- 在網路通訊中應用Protobuf
- 用C++ Builder來定製系統選單(轉)C++UI
- C++用libcurl庫進行http網路通訊程式設計C++HTTP程式設計
- C++ Builder 高手進階 (五)用BCB編寫多執行緒應用程式 (轉)C++UI執行緒
- c++ builder中的ado使用 (轉)C++UI
- C++ BUILDER 訊息處理的深入探索 (轉)C++UI
- (轉)Linux下 C++呼叫C 實現socket網路通訊程式設計LinuxC++程式設計
- VC在windows下編寫用於序列通訊的程式 (轉)Windows
- 網路通訊程式設計程式設計
- 用C#Builder編寫螢幕保護程式 (轉)UI
- 在C++ Builder中定義事件 (轉)C++UI事件
- C++各大有名庫的介紹——網路通訊C++
- 網路通訊
- 用C++ Builder檢測Windows的啟動模式(轉)C++UIWindows模式
- C++ Qt開發:QTcpSocket網路通訊元件C++QTTCP元件
- C++ Qt開發:QUdpSocket網路通訊元件C++QTUDP元件
- Automation In C++ Builder (轉)C++UI
- C++ 用libcurl庫進行http通訊網路程式設計C++HTTP程式設計
- 樂訊通雲通訊:物聯網路卡在智慧路燈的應用
- 用C++ Builder在桌面上畫圖 (轉)C++UI
- udp網路通訊UDP
- 深入C++ Builder之編寫自己的元件 -深入分析VCL繼承、訊息機制(2) (轉)C++UI元件繼承
- 深入C++ Builder之編寫自己的元件-深入分析VCL繼承、訊息機制(3) (轉)C++UI元件繼承
- 樂訊通雲通訊:物聯網路卡在林業中的應用
- 網路通訊2:TCP通訊實現TCP
- 網路通訊3:TCP互動通訊TCP
- 網路通訊2:TCP簡單通訊TCP
- Borland C++ Builder的API後門 (轉)C++UIAPI
- 文字水印技術與網路安全通訊 (轉)
- 樂訊通雲通訊:物聯網路卡在交通運輸中的應用
- 樂訊通雲通訊:物聯網路卡在共享廣告器中的應用
- 樂訊通雲通訊:物聯網路卡在充電樁中的應用
- 樂訊通雲通訊:物聯網路卡在兒童手錶中的應用
- 樂訊通雲通訊:物聯網路卡在智慧醫療中的應用
- 串列埠通訊應用程式的解決方案 (轉)串列埠