サンプルコード

入力されたホスト名とファイル名で、サーバ側と接続しデータを入手するプログラムです。 ソケット関係のコード以外のものが多いので見づらいかとは思いますがソケット部分だけを 載せると動かないときにどこが問題なのかわからないと思いこの形にしました。

テストではHTMLファイルしか指定していないので、他の形式のファイルを指定した場合は 私にもよく分かりません。また文字コードがEUCの場合はエディットコントロールに表示される文字は 正しく表示されません(これはHTMLファイルで保存してブラウザで開けば正しく表示されると思います)。 また、受信するときにCRが受信できていないのか、エディットコントロールで表示するとき改行が うまくできてません。(ローカルでやるとうまく行かなかったのに、インターネットに接続してやったらうまくいった・・・)

おかしいところがあったら、掲示板やメールで連絡ください

インデントが滅茶苦茶になってるみたいです

#define ID_RUN    1000

#include <windows.h>
#include <winsock.h>

int GetFile(HWND,HWND,LPCSTR,LPCSTR);
LONG WINAPI WndProc(HWND,UINT,WPARAM,LPARAM);

////////////////////////////////////////////////////////////

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszCmdLine,int nCmdShow)
{
    static char szAppName[]="ソケット用プログラム";
    WNDCLASS wc;
    HWND hwnd;
    MSG msg;

    // 初期化
    //WSAStartupは成功すると0を返すので、それ以外は失敗とする

    WORD version = MAKEWORD(1,1);//ヴァージョンは1.1
    WSADATA wsa;
    if(WSAStartup(version, &wsa)!=0)
    {
        MessageBox(NULL,"WSAStartupに失敗","失敗",MB_OK);
        return 0;
    }
    
    //要求したバージョンのものが得られなかった場合は失敗とする
    if (wsa.wVersion != version)
	{
        MessageBox(NULL,"要求したWinsockのバージョンが得られませんでした","失敗",MB_OK);
        //割り当てたリソースを解放する
		WSACleanup();
		return 0;
	}
	
    //Winsockと関係ないです
	wc.style=0;
	wc.lpfnWndProc=(WNDPROC) WndProc;
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hInstance=hInstance;
	wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	wc.hCursor=LoadCursor(NULL,IDC_ARROW);
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW);
        wc.lpszMenuName=NULL;
	wc.lpszClassName=szAppName;
	RegisterClass(&wc);
	hwnd=CreateWindow(szAppName,szAppName,WS_SYSMENU,200,200,
        400,310,HWND_DESKTOP,NULL,hInstance,NULL);
       
        ShowWindow(hwnd,nCmdShow);
	UpdateWindow(hwnd);
	
	while(GetMessage(&msg,NULL,0,0))
	{
	   TranslateMessage(&msg);
	   DispatchMessage(&msg);
	}

    //割り当てたリソースを解放する
  	WSACleanup();
	return msg.wParam;
}

////////////////////////////////////////////////////////////

int GetFile(HWND hwnd,HWND memo,LPCSTR hostname, LPCSTR filename)
{
    IN_ADDR       inaddr;
    LPHOSTENT	  hostent;
    SOCKET	  sock;	
    SOCKADDR_IN   sockaddr;
    int ret,readbyte=0;
//recvを繰り返し実行してもうまく動くことを確認するためbufferのサイズが小さくなってます
    char buffer[64],output[1024*64];
    memset(output,'\0',sizeof output);

    //ドット表記のIPアドレスをunsigned long値に変換する命令
    inaddr.s_addr = inet_addr(hostname);


    //ドット表記でなかった場合はホスト名が入っているとみなしてホストを割り出す	
    if (inaddr.s_addr == INADDR_NONE)      
        hostent=gethostbyname(hostname);
    
    else //IPアドレスからホストを割り出す
        hostent=gethostbyaddr((const char *)&inaddr, sizeof(struct in_addr), AF_INET);
    
    //ホスト名がなかったか、ネットワークに接続できなかった
    if (hostent == NULL)
    {
        MessageBox(NULL,"指定されたホストがみつかりませんでした","失敗",MB_OK);
        return 0;
    }

    //ソケットを作成する
    sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    //ソケットの作成に失敗
    if (sock==INVALID_SOCKET)
    {
        MessageBox(NULL,"ソケットが作成できませんでした","失敗",MB_OK);
        return 0;
    }

    //必要なパラメータの設定
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons(80);    
    sockaddr.sin_addr = *((LPIN_ADDR)*hostent->h_addr_list);

    //サーバ側に接続する
    ret=connect(sock, (LPSOCKADDR)&sockaddr, sizeof(SOCKADDR_IN));
    
    //接続できなかった
    if (ret == SOCKET_ERROR)
	{
        MessageBox(NULL,"接続できませんでした","失敗",MB_OK);
        closesocket(sock);
		return 0;
	}

    //指定したファイル名を送信する
    //数バイトだし一発で送れるでしょ(一応ちゃんと実装してください)
    wsprintf(buffer, "GET %s\n",filename);
    ret = send(sock,buffer,strlen(buffer),0);

    //送信失敗
    if (ret == SOCKET_ERROR)
	{
        MessageBox(NULL,"送信できませんでした","失敗",MB_OK);
		closesocket(sock);	
        return 0;
	}

    while(1)
	{
        memset(buffer,'\0',sizeof buffer);
        ret = recv(sock, buffer, sizeof(buffer), 0);        
        
        memcpy(output+readbyte,buffer,ret);
        readbyte+=ret;
        
        //エラー
        if (ret == SOCKET_ERROR)
            break;
        
        //サーバ側が切断した(これでデータ送信が終わったと勝手に判断する)
        if (ret == 0)
            break;        
    }
    
    SetWindowText(memo,"");
    SetWindowText(memo,output);

    //ソケット切断
    closesocket(sock);	
    
    return 1;
}


//Winsockと関係ないです
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{

	PAINTSTRUCT ps;
	HDC hdc; 
    static HWND output,file,host,button;
    char moji[256],moji2[256];
    
    switch(message)
    {
    case WM_CREATE:         

        //出力ウィンドウ、ホスト名,ファイル名指定ウィンドウ,実行ボタンを生成する
        output=CreateWindow("EDIT","",
            WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL 
            | ES_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL,
            20,30,350,150,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),NULL);
        host=CreateWindow("EDIT","",WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
            20,210,150,20,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),NULL);
        file=CreateWindow("EDIT","",WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
            200,210,150,20,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),NULL);
        button=CreateWindow("BUTTON","実行",WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE,
            140,250,80,30,hwnd,(HMENU)ID_RUN,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),NULL);

        break;
    
    case WM_PAINT:
        hdc=BeginPaint(hwnd,&ps);   
        SetBkMode(hdc,TRANSPARENT);
        strcpy(moji,"受信メッセージ");
        TextOut(hdc,5,5,moji,strlen(moji));
        strcpy(moji,"ホスト名");
        TextOut(hdc,5,190,moji,strlen(moji));
        strcpy(moji,"ファイル名");
        TextOut(hdc,185,190,moji,strlen(moji));
        EndPaint(hwnd,&ps);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);	
		break;	
    case WM_COMMAND:          
        switch(LOWORD(wParam)) 
        {
            //ホスト名ファイル名を指定してGetFileを呼び出す
        case ID_RUN:
            GetWindowText(host,moji,sizeof moji);
            GetWindowText(file,moji2,sizeof moji2);
            GetFile(hwnd,output,moji,moji2);
            break;
        }
    }
    return DefWindowProc(hwnd,message,wParam,lParam);
}