MFCソケット簡易サーバーとクライアントソース


以下はSocketを使用して書かれた簡単なサーバとクライアントの一部のコードで、主に初心者にsocket通信の原理とコードの作成方法を知らせます.
#include "stdafx.h"
#include "MTServer.h"
SOCKET server;
using namespace std;
UINT  MTServerThread(LPVOID pParam);
UINT  ClientThread(LPVOID pParam);
BOOL ParseCmd(char *str, CString& cmd, CString& params);
BOOL SendFile(SOCKET s, CString fname);
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;  
    cout << "Press ESCAPE to terminate program\r
"; AfxBeginThread(MTServerThread,0); while(_getch()!=27); closesocket(server); WSACleanup(); return nRetCode; } UINT MTServerThread(LPVOID pParam) { WSADATA wsaData; sockaddr_in local; int wsaret=WSAStartup(0x101,&wsaData); if(wsaret!=0) { return 0; } local.sin_family=AF_INET; local.sin_addr.s_addr=INADDR_ANY; local.sin_port=htons((u_short)20248); server=socket(AF_INET,SOCK_STREAM,0); if(server==INVALID_SOCKET) { return 0; } if(bind(server,(sockaddr*)&local,sizeof(local))!=0) { return 0; } if(listen(server,10)!=0) { return 0; } SOCKET client; sockaddr_in from; int fromlen=sizeof(from); while(true) { client=accept(server, (struct sockaddr*)&from,&fromlen); AfxBeginThread(ClientThread,(LPVOID)client); } return 0; } UINT ClientThread(LPVOID pParam) { char buff[512]; CString cmd; CString params; int n; int x; BOOL auth=false; SOCKET client=(SOCKET)pParam; strcpy(buff,"#Server Ready.\r
"); send(client,buff,strlen(buff),0); while(true) { n=recv(client,buff,512,0); if(n==SOCKET_ERROR ) break; buff[n]=0; if(ParseCmd(buff,cmd,params)) { if(cmd=="QUIT") break; if(cmd=="AUTH") { if(params=="passwd") { auth=true; strcpy(buff,"#You are logged in.\r
"); } else { strcpy(buff,"!Bad password.\r
"); } send(client,buff,strlen(buff),0); } if(cmd=="FILE") { if(auth) { if(SendFile(client,params)) sprintf(buff,"#File %s sent successfully.\r
",params); else sprintf(buff,"!File %s could not be opened.\r
",params); x=send(client,buff,strlen(buff),0); } else { strcpy(buff,"!You are not logged in.\r
"); send(client,buff,strlen(buff),0); } } } else { strcpy(buff,"!Invalid command.\r
"); send(client,buff,strlen(buff),0); } } closesocket(client); return 0; } BOOL ParseCmd(char *str, CString& cmd, CString& params) { int n; CString tmp=str; tmp.TrimLeft(); tmp.TrimRight(); if((n=tmp.Find(' '))==-1) { tmp.MakeUpper(); if(tmp!="QUIT") return false; cmd=tmp; return true; } cmd=tmp.Left(n); params=tmp.Mid(n+1); cmd.MakeUpper(); if((cmd!="AUTH") && (cmd!="FILE")) return false; return true; } BOOL SendFile(SOCKET s, CString fname) { CFile f; BOOL p=f.Open(fname,CFile::modeRead); char buff[1024]; int y; int x; if(!p) return false; while(true) { y=f.Read(buff,1024); x=send(s,buff,y,0); if(y<1024) { f.Close(); break; } } return true; }

クライアントのコードの一部を次に示します.
#include "stdafx.h"
#include "MTSClient.h"
int EndFile(char *buff, int len) ;
int NoFile(char *buff, int len) ;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    const char* servername="127.0.0.1";
    if(argc<2)
    {
        cout << "Usage :- mtsclient [file1] [file2] [file3] ....\r
"; return 0; } WSADATA wsaData; struct hostent *hp; unsigned int addr; struct sockaddr_in server; int wsaret=WSAStartup(0x101,&wsaData); if(wsaret) return 0; SOCKET conn; conn=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(conn==INVALID_SOCKET) return 0; if(inet_addr(servername)==INADDR_NONE) { hp=gethostbyname(servername); } else { addr=inet_addr(servername); hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET); } if(hp==NULL) { closesocket(conn); return 0; } server.sin_addr.s_addr=*((unsigned long*)hp->h_addr); server.sin_family=AF_INET; server.sin_port=htons(20248); if(connect(conn,(struct sockaddr*)&server,sizeof(server))) { closesocket(conn); return 0; } char buff[512]; int z; z=recv(conn,buff,512,0); buff[z]=0; strcpy(buff,"auth passwd\r
"); send(conn,buff,strlen(buff),0); z=recv(conn,buff,512,0); buff[z]=0; for(int j=1;j<argc;j++) { sprintf(buff,"file %s\r
",argv[j]); send(conn,buff,strlen(buff),0); CFile f; char *fname; char fname2[256]; if(!(fname=strrchr(argv[j],'\\'))) strcpy(fname2,argv[j]); else strcpy(fname2,fname+1); cout << fname2 << " has been saved.\r
"; f.Open(fname2,CFile::modeCreate | CFile::modeWrite); bool first=true; bool second=false; while(true) { z=recv(conn,buff,128,0); if(z==SOCKET_ERROR) { cout << "\r
\r
socket error socket error socket error\r
"; break; } if(second) { if(NoFile(buff,128)<128) { cout << "File " << argv[j] << " not found on server\r
"; break; } second=false; } if(first) { if(NoFile(buff,128)<128) { cout << "File " << argv[j] << " not found on server\r
"; break; } first=false; second=true; } int b; if((b=EndFile(buff,z))<z) { f.Write(buff,b); cout << fname2 << " has been saved.\r
"; break; } f.Write(buff,z); } f.Close(); } closesocket(conn); WSACleanup(); return 0; } int EndFile(char *buff, int len) { int pos=len; for(int u=0;u<(len-4);u++) { if(buff[u]=='#') if(buff[u+1]=='F') if(buff[u+2]=='i') if(buff[u+3]=='l') if(buff[u+4]=='e') { pos=u; break; } } return pos; } int NoFile(char *buff, int len) { int pos=len; for(int u=0;u<(len-4);u++) { if(buff[u]=='!') if(buff[u+1]=='F') if(buff[u+2]=='i') if(buff[u+3]=='l') if(buff[u+4]=='e') { pos=u; break; } } return pos; }

このコードは、ネットブックのソースコードです.