在7月4日看完sockcomp.pas后,我决定用socket api来写一个客户端和服务器并且同时支持TCP,UDP协议,于是我就去做,现将代码贴出来(已调试通过) Socket api Client: #ifndef UDPClientH #define UDPClientH #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <stdio.h> #include "CCEdit.h" #define WM_SOCK WM_USER+100 class TLANForm : public TForm { __published: // IDE-managed Components TEdit *Port; TLabel *Label1; TLabel *Label2; TComboBox *Prot; TButton *Button1; TLabel *Label3; TEdit *Addr; TCCEdit *TxtEdit; void __fastcall FormCreate(TObject *Sender); void __fastcall Button1Click(TObject *Sender); void __fastcall FormDestroy(TObject *Sender); private: // User declarations void __fastcall OnRecv(TMessage &Message); public: // User declarations __fastcall TLANForm(TComponent* Owner); BEGIN_MESSAGE_MAP VCL_MESSAGE_HANDLER(WM_SOCK,TMessage,OnRecv); END_MESSAGE_MAP(TForm); }; extern PACKAGE TLANForm *LANForm; #endif .cpp File #include <vcl.h> #pragma hdrstop #include "UDPClient.h" #include "WinSock.h" #pragma package(smart_init) #pragma link "CCEdit" #pragma resource "*.dfm" TLANForm *LANForm; enum PROTO {TCP=0,UDP=1}; SOCKET m_Socket=INVALID_SOCKET; PROTO m_Protocol=TCP; __fastcall TLANForm::TLANForm(TComponent* Owner) : TForm(Owner) {
} void __fastcall TLANForm::FormCreate(TObject *Sender) { ::SendMessage(Prot->Handle,CB_SETCURSEL,0,0); } void __fastcall TLANForm::OnRecv(TMessage &Message) { char buf[4096]; int nLen; struct sockaddr_in from; int nLength=sizeof(struct sockaddr_in); switch(WSAGETSELECTEVENT(Message.LParam)) { case FD_READ: switch(m_Protocol) { case TCP: nLen=recv(m_Socket,buf,4096,0); if(nLen>0){ buf[nLen]='\0'; TxtEdit->Text="Received Length:"+String(nLen)+"\r\n"+StrPas(buf); } break; case UDP: nLen=recvfrom(m_Socket,buf,4096,0,(struct sockaddr*)&from,&nLength); if(nLen>0){ buf[nLen]='\0'; TxtEdit->Text="Received Length:"+String(nLen)+"\r\n"+StrPas(buf); } break; } break; case FD_CLOSE: closesocket(m_Socket); break; } }
void __fastcall TLANForm::Button1Click(TObject *Sender) { char szTmp[256],buf[4096]; int nSize=0; UINT m_Port; AnsiString addr; addr=Addr->Text.Trim(); if(addr.IsEmpty()){ ::MessageBox(0,"Please enter the server IP!","Error",MB_OK+MB_ICONERROR); return; } unsigned long nAddr=inet_addr(addr.c_str()); if(nAddr==INADDR_NONE){ ::MessageBox(0,"Bad Internet IP!","Error",MB_OK+MB_ICONERROR); return;}
try { m_Port=Port->Text.ToInt(); } catch(Exception &e) { ::MessageBox(0,e.Message.c_str(),"Error",MB_OK+MB_ICONERROR); return; } switch(Prot->ItemIndex) { case 0: m_Protocol=TCP; break; case 1: m_Protocol=UDP; break; } if(TxtEdit->Text.IsEmpty()){ ::MessageBox(0,"Please enter the text you want to send!","Error",MB_OK+MB_ICONERROR); return;}
file://Initialize Winsocket WSAData wsaData; ::ZeroMemory(&wsaData,sizeof(WSAData)); WORD version=MAKEWORD(2,0); if(::WSAStartup(version,&wsaData)){ sprintf(szTmp,"Failed to initial winsock enviroment!,error no:%d",::WSAGetLastError()); return;}
file://Obtain the active connection char ComputerName[255]; gethostname(ComputerName,255); struct hostent* he=gethostbyname(ComputerName); if(!he){ sprintf(szTmp,"Failed to get information to host!","Error",MB_OK+MB_ICONERROR); ::WSACleanup(); return; } file://create new socket m_Socket=INVALID_SOCKET; switch(m_Protocol) { case TCP: m_Socket=socket(AF_INET,SOCK_STREAM,0); break; case UDP: m_Socket=socket(AF_INET,SOCK_DGRAM,0); break; } if(m_Socket==INVALID_SOCKET){ sprintf(szTmp,"Failed to create a new socket!,error no:%d",::WSAGetLastError()); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); ::WSACleanup(); return; } file://bind socket struct sockaddr_in client; unsigned long nClient; memcpy(&nClient,he->h_addr_list[0],sizeof(int)); if(nClient==INADDR_NONE){ sprintf(szTmp,"Failed to obtain the local machine's IP!","Error",MB_OK+MB_ICONERROR); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); closesocket(m_Socket); ::WSACleanup(); return; } client.sin_family=AF_INET; client.sin_port=0; client.sin_addr.S_un.S_addr=(int)nClient; if(bind(m_Socket,(struct sockaddr*)&client,sizeof(struct sockaddr))){ sprintf(szTmp,"Failed to bind socket!","Error",MB_OK+MB_ICONERROR); closesocket(m_Socket); ::WSACleanup(); return;} file://connect socket struct sockaddr_in To; To.sin_family=AF_INET; To.sin_port=htons(m_Port); To.sin_addr.S_un.S_addr=(int)nAddr; fd_set FDSET; FD_ZERO(&FDSET); FD_SET(m_Socket,&FDSET);
if(m_Protocol==TCP){ if(connect(m_Socket,(struct sockaddr*)&To,sizeof(struct sockaddr))){ sprintf(szTmp,"Failed to connect the object!,error no:%d",::WSAGetLastError()); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); closesocket(m_Socket); ::WSACleanup(); return; } int nError=select(1,0,&FDSET,0,0); if(nError<=0){ sprintf(szTmp,"Failed to select socket!,error no:%d",::WSAGetLastError()); closesocket(m_Socket); ::WSACleanup(); return;} } file://Send data int nLen=TxtEdit->Text.Length(); if(nLen>4096){ sprintf(szTmp,"The buffer is too size to send,it shoud not be more than 4096 bytes!"); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); closesocket(m_Socket); ::WSACleanup(); return; } strncpy(buf,TxtEdit->Text.c_str(),nLen); switch(m_Protocol) { case TCP: nSize=send(m_Socket,buf,nLen,0); file://ShowMessage(nSize); break; case UDP: nSize=sendto(m_Socket,buf,nLen,0,(struct sockaddr*)&To,sizeof(struct sockaddr)); file://ShowMessage(nSize); break;
} if(::WSAAsyncSelect(m_Socket,Handle,WM_SOCK,FD_READ|FD_CLOSE)){ sprintf(szTmp,"Failed to register socket event!,error no:%d",::WSAGetLastError()); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); closesocket(m_Socket); ::WSACleanup(); return;} } void __fastcall TLANForm::FormDestroy(TObject *Sender) { closesocket(m_Socket); ::WSACleanup(); }
Socket api Server: .h File #ifndef UDPServerH #define UDPServerH #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <stdio.h> #include "WinSock.h" /*#define WM_SOCKET WM_USER+1000 #define INITSOCKETSUCCESS 0 #define INITSOCKETFAILURE 1 #define CREATELISTENSOCKETSUCCESS 2 #define CREATELISTENSOCKETFAILURE 3 #define SETLISTENSOCKETSUCCESS 4 #define SETLISTENSOCKETFAILURE 5 #define BINDLISTENSOCKETSUCCESS 6 #define BINDLISTENSOCKETFAILURE 7 #define LISTENSOCKETSUCCESS 8 #define LISTENSOCKETFAILURE 9 #define ACCEPTSOCKETSUCCESS 10 #define ACCEPTSOCKETFAILURE 11 */ class TPSTNForm : public TForm { __published: // IDE-managed Components TEdit *Port; TLabel *Label1; TMemo *Memo1; TButton *Button1; TButton *Button2; TLabel *Label2; TComboBox *Prot; void __fastcall Button1Click(TObject *Sender); void __fastcall Button2Click(TObject *Sender); void __fastcall FormCreate(TObject *Sender); void __fastcall FormDestroy(TObject *Sender); private: // User declarations public: // User declarations __fastcall TPSTNForm(TComponent* Owner); }; enum PROTO {TCP,UDP}; class TCommunication:public TThread file://Communication Thread { private: SOCKET m_AcceptSocket; char szTmp[256];//ERROR MESSAGE public: __fastcall TCommunication(SOCKET m_Socket,bool CreateSuspended); __fastcall ~TCommunication(); protected: virtual void __fastcall Execute(); }; class TListenThread:public TThread file://Listen Thread { private: WSAData wsaData; struct sockaddr_in server; fd_set FDS; UINT m_Port; PROTO m_Protocol; char szTmp[256];//Error Message public: SOCKET m_Socket; void __fastcall DoError(); void __fastcall InitSocket(); void __fastcall CreateListenSocket(); void __fastcall SetListenSocket(); void __fastcall BindListenSocket(); void __fastcall ListenSocket();
public: __fastcall TListenThread(PROTO m_ProtocolA,UINT m_PortA,bool CreateSuspended); virtual __fastcall ~TListenThread(); protected: virtual void __fastcall Execute(); }; extern PACKAGE TPSTNForm *PSTNForm; #endif .cpp File #include <vcl.h> #pragma hdrstop #include "UDPServer.h" #pragma package(smart_init) #pragma resource "*.dfm" TPSTNForm *PSTNForm; TListenThread *pThread=0; file://******************************CLASS TCommunication For TCP**************************************************** __fastcall TCommunication::TCommunication(SOCKET m_Socket,bool CreateSuspended):TThread(FALSE) { m_AcceptSocket=m_Socket; szTmp[0]='\0'; FreeOnTerminate=true; } __fastcall TCommunication::~TCommunication() { // closesocket(m_AcceptSocket); } void __fastcall TCommunication::Execute() { char buf[4096]; int nSize=0; nSize=recv(m_AcceptSocket,(char FAR*)buf,4096,0); if(nSize>0) { buf[nSize]='\0'; file://Display PSTNForm->Memo1->Lines->Add("Received Length:"+String(nSize)); PSTNForm->Memo1->Lines->Add("Received:"+StrPas(buf)); file://Deliver ::Sleep(100); send(m_AcceptSocket,buf,nSize,0); }
} file://******************************CLASS TListenThread***************************************************** __fastcall TListenThread::TListenThread(PROTO m_ProtocolA,UINT m_PortA,bool CreateSuspended):TThread(FALSE) { m_Socket=INVALID_SOCKET; m_Port=m_PortA; m_Protocol=m_ProtocolA; szTmp[0]='\0'; ::ZeroMemory(&wsaData,sizeof(WSAData)); ::ZeroMemory(&server,sizeof(struct sockaddr_in)); FreeOnTerminate=TRUE;//Automatically delete while terminating. } __fastcall TListenThread::~TListenThread() { closesocket(m_Socket); ::WSACleanup(); m_Socket=INVALID_SOCKET; m_Port=0; m_Protocol=TCP; szTmp[0]='\0'; ::ZeroMemory(&wsaData,sizeof(WSAData)); ::ZeroMemory(&server,sizeof(struct sockaddr_in)); } void __fastcall TListenThread::DoError() { if(m_Socket!=INVALID_SOCKET) closesocket(m_Socket); WSACleanup(); return; } void __fastcall TListenThread::InitSocket() { WORD version=MAKEWORD(2,0); if(::WSAStartup(version,&wsaData)){ sprintf(szTmp,"Failed to intiailize socket,error no:%d",::WSAGetLastError()); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); DoError(); return; } } void __fastcall TListenThread::CreateListenSocket() { switch(m_Protocol) { case UDP: m_Socket=socket(AF_INET,SOCK_DGRAM,0); break; case TCP: m_Socket=socket(AF_INET,SOCK_STREAM,0); break; default: sprintf(szTmp,"Error protocol!"); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); DoError(); break; } if(m_Socket==INVALID_SOCKET){ sprintf(szTmp,"Failed to create socket!"); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); DoError(); return; } } void __fastcall TListenThread::SetListenSocket() { server.sin_family=AF_INET; server.sin_port=htons(m_Port); server.sin_addr.S_un.S_addr=INADDR_ANY; int NewOpenType=SO_SYNCHRONOUS_NONALERT; if(setsockopt(INVALID_SOCKET,SOL_SOCKET,SO_OPENTYPE,(char*)&NewOpenType,4)){ sprintf(szTmp,"Set socket option error,error no:%d",::WSAGetLastError()); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); DoError(); return; } } void __fastcall TListenThread::BindListenSocket() { if(bind(m_Socket,(sockaddr*)&server,sizeof(struct sockaddr_in))){ sprintf(szTmp,"Failed to bind socket,error no:%d",::WSAGetLastError()); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); DoError(); return; }
} void __fastcall TListenThread::ListenSocket() { if(listen(m_Socket,SOMAXCONN)){ sprintf(szTmp,"listen error,error no:%d",::WSAGetLastError()); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); DoError(); return; } file://Determine whether there is any connection FD_ZERO(&FDS); FD_SET(m_Socket,&FDS); } void __fastcall TListenThread::Execute() { char buf[4096]; struct sockaddr_in from; file://for UDP int nLen=sizeof(from),nSize=0; file://for UDP InitSocket(); CreateListenSocket(); SetListenSocket(); BindListenSocket(); if(m_Protocol==UDP){ while(!Terminated){ int nSize=recvfrom(m_Socket,buf,4096,0,(struct sockaddr*)&from,&nLen); if(nSize>0){ buf[nSize]='\0'; PSTNForm->Memo1->Lines->Add("Received Length:"+String(nSize)); PSTNForm->Memo1->Lines->Add("Received:"+StrPas(buf)); ::Sleep(100); sendto(m_Socket,buf,nSize,0,(struct sockaddr*)&from,sizeof(struct sockaddr_in)); } else return;
} } ListenSocket(); struct sockaddr_in client; int nLength=sizeof(struct sockaddr_in); while(!Terminated){ int nError=select(1,&FDS,0,0,0); if(nError<=0) Terminate(); SOCKET m_AcceptSocket=accept(m_Socket,(struct sockaddr*)&client,&nLength); if(m_AcceptSocket==INVALID_SOCKET){ sprintf(szTmp,"Failed to execute accept,error no:%d",::WSAGetLastError()); ::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR); DoError(); Terminate(); return; } TCommunication *pCThread=new TCommunication(m_AcceptSocket,FALSE); pCThread->Terminate(); pCThread->WaitFor(); } } file://************************PSTNForm*********************************************// __fastcall TPSTNForm::TPSTNForm(TComponent* Owner) : TForm(Owner) { } void __fastcall TPSTNForm::Button1Click(TObject *Sender) { Close(); } void __fastcall TPSTNForm::Button2Click(TObject *Sender) { if(pThread){ pThread->Suspend(); pThread->Terminate(); delete pThread; pThread=0; } UINT m_Port; try { m_Port=Port->Text.ToInt(); } catch(Exception &e) { ::MessageBox(0,e.Message.c_str(),"Error",MB_OK+MB_ICONERROR); return; } PROTO m_Protocol; switch(Prot->ItemIndex) { case 0: m_Protocol=TCP; break; case 1: m_Protocol=UDP; break; default: break; } pThread=new TListenThread(m_Protocol,m_Port,FALSE); file://pThread->Terminate(); } void __fastcall TPSTNForm::FormCreate(TObject *Sender) { ::SendMessage(Prot->Handle,CB_SETCURSEL,0,1); }
void __fastcall TPSTNForm::FormDestroy(TObject *Sender) { if(pThread){ pThread->Suspend(); pThread->Terminate();} } 上面的代码,各位可根据自已的需要和针对自已的应用,在数据处理方面加以改进就可以了。
再次声明,上述代码中出现的file:前缀这是csdn文档编辑器自动加的,各位凡是见到file:前缀就表示它是注释部分,特此声明,以免误解。

|