장성호 님이 쓰신 글 :
: 보통 Socket이 Close될때 Client , Server간에 서로 close하겠다고
: 정보를 주고 받고 close하는게 정상적인 close인데...
:
: Client에서 그런 정보를 보내지 못하고 끊어지면 위와같은 에러가 뜨는것 같습니다.
:
: 예를 들어 - 네트워크가 갑자기 끊어지거나
: - Client프로그램이 갑자기 죽거나 등등의 현상이 발생하면
:
:
: 제대로된 해결은 아닌것 같은데..
: 그냥 Read부분에 try ~ catch 로 잡으시면 될듯 합니다.
:
: try
: {
: int rslt=pStream->Read(Buffer, 100);
: if( rslt== 0)
: {
: // 입력된 값이 없으면 종료
: HIndex=fmServer->cbSocketHandle->Items->IndexOf(IntToStr(ClientSocket->SocketHandle));
: fmServer->cbSocketHandle->Items->Delete(HIndex);
: if(fmServer->cbSocketHandle->Items->Count==0)
: {
: fmServer->cbSocketHandle->Text="연결된 소켓 없음";
: }
:
: ClientSocket->Close();
: }
:
: fmServer->mbChat->Lines->Add(String(Buffer));
: fmServer->BroadCastOut(String(Buffer));
: fmServer->edtActiveThread->Text=fmServer->ServerSocket1->Socket->ActiveThreads;
: }
: catch(...)
: {
: // 입력된 값이 없으면 종료
: HIndex=fmServer->cbSocketHandle->Items->IndexOf(IntToStr(ClientSocket->SocketHandle));
: fmServer->cbSocketHandle->Items->Delete(HIndex);
: if(fmServer->cbSocketHandle->Items->Count==0)
: {
: fmServer->cbSocketHandle->Text="연결된 소켓 없음";
: }
:
: ClientSocket->Close();
: }
:
: //------------------------------------------
: 구글신에 의지하여 TServerClientThread 예제 수십개를 보았지만
: 대부분 아래와 같은 처리하더군요
: 예외는 HandleException(); 으로...
:
:
: void __fastcall TMyServerThread::ClientExecute()
: {
: while (!Terminated && ClientSocket->Connected) // make sure connection is active
: {
: try
: {
: TWinSocketStream *pStream = new TWinSocketStream(ClientSocket, 60000);
: try
: {
: char buffer[50];
: memset(buffer, 0, sizeof(buffer));
: if (pStream->WaitForData(6000)) // give the client 60 seconds to start writing
: {
:
: if (pStream->Read(buffer, sizeof(buffer)) == 0)
: ClientSocket->Close(); // if can't read in 60 seconds, close the connection
: // now process the request
: }
: else
: ClientSocket->Close();
: }
: __finally
: {
: delete pStream;
: }
: }
: catch (...)
: {
: HandleException();
: }
: }
: }
:
: 참고 하세요
:
http://dn.codegear.com/article/26276
:
http://topic.csdn.net/t/20060704/23/4860640.html
:
http://duketown.com/marcel/server.shtml
:
http://www.delmadang.com/cwb-bin/CrazyWWWBoard.exe?mode=read&num=754&page=49&db=dmdlec3&backdepth=3
:
http://topic.csdn.net/t/20020304/19/554711.html
:
http://delphi.newswhat.com/geoxml/forumhistorythread?groupname=borland.public.delphi.internet.winsock&messageid=40863a71@newsgroups.borland.com
:
http://www.ipc.hokusei.ac.jp/~z00104/delphi/thread.html
:
http://book.77169.org/ask1/ask100852.htm
:
http://forum.sources.ru/index.php?showtopic=159584
:
:
:
: 그럼..
:
:
:
:
: 짱구오빠 님이 쓰신 글 :
: : Project SocketTread.exe raised exception class ESocketErrro with message 'Read error
: : 64, 지정된 네트워크 이름을 더 이상 사용할 수 없습니다.'. Process stopped. Use Step or Run
: : to Continue.
: :
: : 이런 메시지가 뜹니다.
: :
: : void __fastcall TServerSocketThread::ClientExecute(void)
: : 함수에서
: : if(pStream->WaitForData(300000))
: : 에서 기다리다가 소켓으로 수신되면
: : if(pStream->Read(Buffer, 100) == 0)를 처리한 후
: : 정상적으로 처리된 후
: : 다시
: : if(pStream->WaitForData(300000)) 부분에서
: : 수신을 기다려야 하는데
: : if(pStream->Read(Buffer, 100) == 0)으로 넘아간 후
: : pStream->Read 함수 처리시
: : 위와같은 에러메시지가 나옵니다.
: :
: : 버퍼의 내용이 클리어가 않된건지...
: :
: : 아래 소스는 자료실에 있는 소켓쓰레드를 옮겨서 코딩한 겁니다.
: : 무슨 에러인지 모르겠네요.
: :
: : 그리고 소켓서버의 멀티 쓰레드는 아래와 같이 코딩하면 되는건가요?
: :
: : 도와주세요.
: :
: :
: :
: : 소스 내용입니다.
: :
: : __fastcall TServerSocketThread::TServerSocketThread(bool CreateSuspended, TServerClientWinSocket * ASocket)
: : : TServerClientThread(CreateSuspended, ASocket)
: : {
: : FreeOnTerminate=true;
: : }
: :
: : void __fastcall TServerSocketThread::ClientExecute(void)
: : {
: : int HIndex;
: : TWinSocketStream *pStream; // 소켓을 스트림으로 받음
: : char Buffer[100];
: :
: : memset(Buffer, 0x00, sizeof(Buffer));
: :
: : while (!Terminated && ClientSocket->Connected)
: : {
: : pStream = new TWinSocketStream(ClientSocket, 60000);
: : try
: : {
: : memset(Buffer, 0, sizeof(Buffer));
: : if(pStream->WaitForData(300000))
: : {
: : // 5분간 입력이 없으면 종료
: : if(pStream->Read(Buffer, 100) == 0)
: : {
: : // 입력된 값이 없으면 종료
: : HIndex=fmServer->cbSocketHandle->Items->IndexOf(IntToStr(ClientSocket->SocketHandle));
: : fmServer->cbSocketHandle->Items->Delete(HIndex);
: : if(fmServer->cbSocketHandle->Items->Count==0)
: : {
: : fmServer->cbSocketHandle->Text="연결된 소켓 없음";
: : }
: :
: : ClientSocket->Close();
: : }
: :
: : fmServer->mbChat->Lines->Add(String(Buffer));
: : fmServer->BroadCastOut(String(Buffer));
: : fmServer->edtActiveThread->Text=fmServer->ServerSocket1->Socket->ActiveThreads;
: : }
: : else
: : {
: : HIndex=fmServer->cbSocketHandle->Items->IndexOf(IntToStr(ClientSocket->SocketHandle));
: : fmServer->cbSocketHandle->Items->Delete(HIndex);
: : if(fmServer->cbSocketHandle->Items->Count==0) fmServer->cbSocketHandle->Text="연결된 소켓 없음";
: : ClientSocket->Close();
: : }
: : }
: : __finally
: : {
: : delete pStream;
: : }
: : }
: :
: : //종료시 cbSocketHandle에서 ClientSocketHandle 삭제
: : HIndex=fmServer->cbSocketHandle->Items->IndexOf(IntToStr(ClientSocket->SocketHandle));
: : fmServer->cbSocketHandle->Items->Delete(HIndex);
: : if(fmServer->cbSocketHandle->Items->Count==0)
: : {
: : fmServer->cbSocketHandle->Text="연결된 소켓 없음";
: : }
: : }
: :
: :
: :
: :
: : //---------------------------------------------------------------------------
: :
: : // 쓰레드 외부에서 ClientSocketHandle값으로 CustomWinSocket을 생성하여 접속한 각 클라이언트로
: : // 데이타를 날려준다. - BroadCast
: : void __fastcall TfmServer::BroadCastOut(String SendString)
: : {
: : for(int i=0; i<cbSocketHandle->Items->Count;i++)
: : {
: : TCustomWinSocket *CustomWinSocket = new TCustomWinSocket(StrToInt(cbSocketHandle->Items->Strings[i]));
: : CustomWinSocket->SendText(SendString);
: : // delete CustomWinSocket;
: : }
: : }
: :
: :
: : //---------------------------------------------------------------------------
: :
: : void __fastcall TfmServer::FormCreate(TObject *Sender)
: : {
: : ServerSocket1->Port=2000;
: : ServerSocket1->Open();
: : Sleep(100);
: : Application->ProcessMessages();
: : cntNum=0;
: : }
: : //---------------------------------------------------------------------------
: : void __fastcall TfmServer::ServerSocket1ClientDisconnect(TObject *Sender,
: : TCustomWinSocket *Socket)
: : {
: : mbStat->Lines->Add("사용자가 접속을 종료했습니다.");
: : cntNum--;
: : edtTotalNum->Text=cntNum;
: : }
: : //---------------------------------------------------------------------------
: : void __fastcall TfmServer::ServerSocket1Accept(TObject *Sender,
: : TCustomWinSocket *Socket)
: : {
: : mbStat->Lines->Add("사용자가 접속했습니다.");
: : cntNum++;
: : edtTotalNum->Text=cntNum;
: : }
: : //---------------------------------------------------------------------------
: : void __fastcall TfmServer::ServerSocket1GetThread(TObject *Sender,
: : TServerClientWinSocket *ClientSocket,
: : TServerClientThread *&SocketThread)
: : {
: : // TServerClientThread 를 생성
: : SocketThread = new TServerSocketThread(false, ClientSocket);
: : }
: : //---------------------------------------------------------------------------
: : void __fastcall TfmServer::ServerSocket1GetSocket(TObject *Sender,
: : int Socket, TServerClientWinSocket *&ClientSocket)
: : {
: : // SocketHandle을 저장
: : cbSocketHandle->Items->Add(IntToStr(Socket));
: : if(cbSocketHandle->Items->Count==1)
: : {
: : cbSocketHandle->Text=IntToStr(Socket);
: : }
: : }
: : //---------------------------------------------------------------------------
: : void __fastcall TfmServer::FormClose(TObject *Sender, TCloseAction &Action)
: : {
: : //Server Socket Close
: : ServerSocket1->Close();
: :
: : //Memory Free
: : Action = caFree;
: : }
: : //---------------------------------------------------------------------------
: : void __fastcall TfmServer::ServerSocket1ThreadEnd(TObject *Sender,
: : TServerClientThread *Thread)
: : {
: : edtActiveThread->Text=fmServer->ServerSocket1->Socket->ActiveThreads;
: :
: : }
: : //---------------------------------------------------------------------------
: : void __fastcall TfmServer::ServerSocket1ClientError(TObject *Sender,
: : TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
: : {
: : mbStat->Lines->Add("사용자의 서버에 문제가 있습니다.");
: : }