winsockのエラーについて教えてください

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ayane.ch
記事: 4
登録日時: 4年前

winsockのエラーについて教えてください

#1

投稿記事 by ayane.ch » 4年前

win32APIを使ってチャットするプログラミングを作成したいと思っています。
現在acceptのところでエラー10038と表示されます。
検索するとソケットではないとのことでしたが、SOCKET Newsock;
と宣言しているので、原因がわかりません。
acceptのエラーと、その他間違っているところがあれば、教えてください。


コード:


#include <windows.h> 
#include <stdio.h> 
#define WINDOWS_CLASS_NAME TEXT("WisdomSoft.Sample.Window") 
#pragma comment(lib, "wsock32.lib") 
//#include <winsock2.h> 

#define WM_SOCKET WM_APP 
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam) 
#define WSAGETSELECTERROR(lParam) HIWORD(lParam) 
TEXTMETRIC tm; 


int InitializeWindow(CREATESTRUCT* createWindowArgs){ 
    return 0; 
} 

LRESULT CALLBACK SampleWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 


    PAINTSTRUCT ps; 
    HDC hdc; 
    RECT rt;  //ウィンドウの大きさの定義 
    static HANDLE hFile;  //ファイルのオープンに使用 
    DWORD   dwBytes; 
    static HFONT hfont1; 
    static HFONT hfontOld; 


    //● winsockで利用。 
    WSADATA wsaData;  //初期化で利用。 
    SOCKET sock = INVALID_SOCKET;  //サーバ側のソケット 
    SOCKET Newsock;  //acceptで新たに作成される 
    struct sockaddr_in addr;  //bindで使用 
    struct sockaddr_in client;  //acceptで使用 
    int len;  //client構造体の長さ 
    char buf[10];  //文字の入力用 
    int error;  //エラー処理用 
    int sn; 


    switch (uMsg) 
    { 

    case WM_CREATE: 
    { 
        // ウィンドウ作成時に1回のみ実行される 

        // ↓ ここからwinsockについて。 
        // ↓ ここからwinsockについて。 



        //初期化の処理。 
        error = WSAStartup(MAKEWORD(2, 0), &wsaData); 
        if (error != 0){  //WSAStartupは成功の場合0を返す。 
            return 1; 
        } 

        //ソケットの作成。 
        sock = socket(AF_INET, SOCK_STREAM, 0); 
        if (sock == INVALID_SOCKET){  //socketはエラーの場合INVALID_SOCKETを返す。 
            return 1; 
        } 


        //●非同期の処理。 
        if (WSAAsyncSelect(sock, hwnd, WM_SOCKET, FD_ACCEPT) == SOCKET_ERROR){ 
            Beep(740, 200);  //エラー音 
        } 


        //通信に必要なIPアドレス・ポート番号を持つ構造体。 
        addr.sin_family = AF_INET;  //アドレスファミリ。固定 
        addr.sin_port = htons(12345);  //ポート番号 
        addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);;  //IPアドレス。INADDR_ANYはどのIPでもOK。 

        //↑の構造体を利用 
        //アドレスと結びつける 
        if (bind(sock, (struct sockaddr_in *)&addr, sizeof(addr)) == SOCKET_ERROR){ 
            Beep(740, 200);  //エラー音 
        } 
        //第2引数は、キューの最大サイズ。 
        if (listen(sock, 4) == SOCKET_ERROR){ 
            Beep(740, 200);  //エラー音 
        } 


        //フォント作成。変更しない。 
        hfont1 = CreateFont(16, 8, 0, 0, 
            FW_NORMAL, FALSE, FALSE, 0, 
            SHIFTJIS_CHARSET, 
            OUT_DEFAULT_PRECIS, 
            CLIP_DEFAULT_PRECIS, 
            DEFAULT_QUALITY, DEFAULT_PITCH, "MS ゴシック"); 


        return InitializeWindow((CREATESTRUCT*)lParam); 

        break; 
    } 



    case WM_SOCKET: 
        switch (WSAGETSELECTEVENT(lParam)) { 
        case FD_ACCEPT: 
            //クライアントからの接続許可。 
            len = sizeof(client); 
            Newsock = accept(sock, (struct sockaddr *)&client, &len);  //acceptの第3引数はポインタなので。 
            if (Newsock == INVALID_SOCKET) { 
	        int errcode = WSAGetLastError();
		itoa(errcode, buf, 10);
		MessageBox(NULL, buf, NULL, MB_OK | MB_ICONINFORMATION);
                Beep(740, 200);  //エラー音 
                break; 
            } 

            char buffchat[] = "CHAT"; 
            if (send(Newsock, buffchat, 4, 0) == SOCKET_ERROR){ 
                Beep(740, 200);  //エラー音 
                *buf = WSAGetLastError(); 
            } 
            //●非同期の処理2。 
            WSAAsyncSelect(Newsock, hwnd, WM_SOCKET, FD_READ | FD_CLOSE); 
            break; 

        case FD_READ:{ 
            memset(buf, 0, sizeof(buf)); 
            sn = recv(Newsock, buf, sizeof(buf), 0);   //nにはデータのバイト数が入る 
        }break; 


        case FD_CLOSE:{ 
            //終了処理。 
            closesocket(sock);  //TCPの処理。WSACleanupの上に書く。 
            WSACleanup();  //winsock自体。引数はない。 
        }break; 
        } 


    case WM_PAINT: 
        // TODO: 描画コードをここに追加してください... 
        hdc = BeginPaint(hwnd, &ps); 
        hfontOld = (HFONT)SelectObject(hdc, hfont1); 

        GetTextMetrics(hdc, &tm); 
        TextOut(hdc, 0, (tm.tmHeight), buf, 4); 
        //TextOut(hdc, 15, (tm.tmHeight), "エラー", 6); 

        SelectObject(hdc, hfontOld); 
        EndPaint(hwnd, &ps); 

        break; 

    case WM_DESTROY: 

        //WM_DESTROY ウィンドウの終了と同時にアプリの終了も行う。 
        //PostQuitMessage 引数をwParamに設定し、アプリケーションの終了コードとする。 

        return 0; 
        break; 


    default: 
        return DefWindowProc(hwnd, uMsg, wParam, lParam);//!! 
        //標準的なウィンドウの動作を提供。動いたり拡大したり。 


    } 

    return 0; 
} 



コード:

#include <windows.h>
#include <stdio.h>
#define WINDOWS_CLASS_NAME TEXT("WisdomSoft.Sample.Window")
#pragma comment(lib, "wsock32.lib")
//#include <winsock2.h>

#define WM_SOCKET WM_APP
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
#define WSAGETSELECTERROR(lParam) HIWORD(lParam)
TEXTMETRIC tm;



int InitializeWindow(CREATESTRUCT* createWindowArgs){
	return 0;
}


LRESULT CALLBACK SampleWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

	PAINTSTRUCT ps;
	HDC hdc;
	RECT rt;  //ウィンドウの大きさの定義
	static HANDLE hFile;  //ファイルのオープンに使用
	DWORD   dwBytes;
	static HFONT hfont1;
	static HFONT hfontOld;

	//● winsockで利用。
	WSADATA wsaData;  //初期化に使用。
	struct sockaddr_in server;  //connectにて使用。
	SOCKET sock_C = INVALID_SOCKET;  //クライアント側のソケット
	char buf[100];  //文字列の保管用。
	int error;  //エラー処理用
	int n;

	switch (uMsg)
	{

	case WM_CREATE:

		// ↓ ここからwinsockについて。
		// ↓ ここからwinsockについて。


		//初期化の処理。
		error = WSAStartup(MAKEWORD(2, 0), &wsaData);
		if (error != 0){  //WSAStartupは成功の場合0を返す。
			return 1;
		}

		//ソケットの作成。
		sock_C = socket(AF_INET, SOCK_STREAM, 0);
		if (sock_C == INVALID_SOCKET){  //socketはエラーの場合INVALID_SOCKETを返す。
			Beep(740, 200);  //エラー音;
			return 1;
		}

		//●非同期の処理。
		if (WSAAsyncSelect(sock_C, hwnd, WM_SOCKET, FD_CONNECT | FD_WRITE | FD_READ | FD_CLOSE) == SOCKET_ERROR){
			//if (WSAAsyncSelect(sock_C, hwnd, WM_SOCKET, FD_CONNECT) == SOCKET_ERROR){
			Beep(740, 200);  //エラー音
		}


		//通信に必要なIPアドレス・ポート番号を持つ構造体。
		server.sin_family = AF_INET;  //アドレスファミリ。固定
		server.sin_port = htons(12345);  //ポート番号
		server.sin_addr.S_un.S_addr = inet_addr("192.168.12.345");  //IPアドレス。今回は適当です。
		if (connect(sock_C, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR){
			//Beep(740, 200);  //エラー音
		}


		//フォント作成
		hfont1 = CreateFont(16, 8, 0, 0,
			FW_NORMAL, FALSE, FALSE, 0,
			SHIFTJIS_CHARSET,
			OUT_DEFAULT_PRECIS,
			CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY, DEFAULT_PITCH, "MS ゴシック");


		return InitializeWindow((CREATESTRUCT*)lParam);

		break;


	case WM_SOCKET:
		switch (WSAGETSELECTEVENT(lParam)) {

		case FD_READ:
			memset(buf, 0, sizeof(buf));
			n = recv(sock_C, buf, sizeof(buf), 0);   //nにはデータのバイト数が入る
			break;

		case FD_CLOSE:
			//終了処理。
			closesocket(sock_C);  //TCPの処理。WSACleanupの上に書く。
			WSACleanup();  //winsock自体。引数はない。
			break;
		}



	case WM_PAINT:
		// TODO: 描画コードをここに追加してください...
		hdc = BeginPaint(hwnd, &ps);
		hfontOld = (HFONT)SelectObject(hdc, hfont1);

		GetTextMetrics(hdc, &tm);

		TextOut(hdc, 0, (tm.tmHeight), buf, 10);
		//TextOut(hdc, 15, (tm.tmHeight), "てすと", 6);

		SelectObject(hdc, hfontOld);
		EndPaint(hwnd, &ps);

		break;


	case WM_DESTROY:

		//WM_DESTROY ウィンドウの終了と同時にアプリの終了も行う。
		//PostQuitMessage 引数をwParamに設定し、アプリケーションの終了コードとする。

		return 0;
		break;


	default:
		return DefWindowProc(hwnd, uMsg, wParam, lParam);//!!
		//標準的なウィンドウの動作を提供。動いたり拡大したり。


	}



	return 0;
}


アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: winsockのエラーについて教えてください

#2

投稿記事 by みけCAT » 4年前

ayane.ch さんが書きました:win32APIを使ってチャットするプログラミングを作成したいと思っています。
作成したいのはプログラムではないのですか?
ayane.ch さんが書きました:現在acceptのところでエラー10038と表示されます。
検索するとソケットではないとのことでしたが、SOCKET Newsock;
と宣言しているので、原因がわかりません。
acceptのエラーと、その他間違っているところがあれば、教えてください。
acceptで使用しているsockは自動変数なので、WM_CREATEの時の代入は反映されず、acceptにはINVALID_SOCKETが渡されるはずです。
変数に適切にstaticをつけるなどして、データが正しく渡されるようにするべきです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ayane.ch
記事: 4
登録日時: 4年前

Re: winsockのエラーについて教えてください

#3

投稿記事 by ayane.ch » 4年前

みけCATさん、ありがとうございます!
プログラムでした、打ち間違えです、申し訳ない・・・

GetMessageでぐるぐる回すので、静的変数だと消えてしまうのですね!
気がつきませんでした・・・

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: winsockのエラーについて教えてください

#4

投稿記事 by みけCAT » 4年前

ayane.ch さんが書きました:GetMessageでぐるぐる回すので、静的変数だと消えてしまうのですね!
静的変数で消えるかどうかはプログラムによります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ayane.ch
記事: 4
登録日時: 4年前

Re: winsockのエラーについて教えてください

#5

投稿記事 by ayane.ch » 4年前

プログラムによるんですね、決めつけないで確認するようにします。

また、今度はconnectでエラー10035が発生したのですが、
こちらについては何がおかしいのでしょうか・・・
図々しくて申し訳ございませんがヒントだけでも頂ければと思います。

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: winsockのエラーについて教えてください

#6

投稿記事 by みけCAT » 4年前

複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ayane.ch
記事: 4
登録日時: 4年前

Re: winsockのエラーについて教えてください

#7

投稿記事 by ayane.ch » 4年前

エラーについては確認したのですが、
何故サーバとクライアントが繋がらないかが不明です…

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: winsockのエラーについて教えてください

#8

投稿記事 by YuO » 4年前

ayane.ch さんが書きました:何故サーバとクライアントが繋がらないかが不明です…
「繋がらない」をどうやって確認しましたか。
元のコードを見る限り,サーバー側のFD_ACCEPT時のコードにブレイクポイントを設定したのでしょうか。

WSAEWOULDBLOCKはエラーとして通知されますが,非同期通信を行う場合においては,実質的にはエラーではありません。
非同期通信をする場合,WSAEWOULDBLOCKが発生する前提でプログラムを組む必要があります。

なお,WSAAsyncSelectのRemarksにあるように,コールバックメッセージのwParamにはメッセージを発生させたソケットが含まれます。
これを使うと複数のソケットを同時に扱うことができるため,コールバックされた時にはwParamをSOCKETにキャストしたものを使った方がよいでしょう。

閉鎖

“C言語何でも質問掲示板” へ戻る