vcネットワークプログラミング(socket)
19840 ワード
インターネットで多くの資料を探しましたが、これらの資料をまとめて、VCの下のsocketプログラミングを詳しく紹介して、サーバークライアントの具体的な例を提供します.あなたの役に立ちたいです.
一、原理部分
(個人的にはこの文章はいいと思いますので、ここに回します.原文の住所:http://dev.yesky.com/78/2683078.shtml)ネットワークプログラミングで最もよく使われるプログラムはCient/Server(クライアント/サーバ)モデルです.この方式では、クライアントアプリケーションはサーバプログラムにサービスを要求する.一つのサービスプログラムは、一般的によく知られているアドレスでサービスに対する要求を傍受し、つまり、サービスプロセスは、クライアントがこのサービスのアドレスに接続要求を提出するまでスリープ状態にある.この時点では、サービスプログラムは"目ざめ"され、お客様にサービスを提供します.お客様の要求に対して適切な反応をします.このようなClient/Serverモデルのネットワークプログラミングを便利にするために、90年代初めに、Microsoftが他のいくつかの会社と共同でWINDOWSの下のネットワークプログラミングインターフェース、つまりWindows Sockets規格を制定しました.これは一つのネットワークプロトコルではなく、一連の開放的で、複数のプロトコルをサポートするWindowsの下のネットワークプログラミングインターフェースです.現在のWinsockは基本的にプロトコルとは関係なくWinsockを使って様々なプロトコルの機能を呼び出すことができますが、よく使われているのはTCP/IPプロトコルです.ソケットは実際にコンピュータに通信ポートを提供しており、このポートを介して任意のソケットインターフェースを有するコンピュータと通信することができる.アプリケーションはネットワーク上で伝送され、受信した情報はこのソケットインターフェースで実現される.マイクロソフトはVisual C++のためにWinsock種類を定義しました.例えば、CAsyncSocket類とCAsyncSocketから派生したCSocket類は簡単に使えます.読者の友達はもちろんこれらの種類を使って自分のネットワークプログラムを実現できますが、Winsock APIプログラミング技術をよりよく知るために、底のAPI関数を使って簡単なWinsockネットワークアプリケーションの設計を実現する方法を検討します.それぞれServer端とClient端でSocketを操作する方法を説明し、TCP/IPに基づくデータ転送を実現し、最後に関連ソースコードを与える.VCでWINSOCKのAPIプログラミング開発を行うには、プロジェクトで次の三つのファイルを使用する必要があります.そうでないとコンパイルエラーが発生します.1.WINSOCK.H:これはWINSOCK APIのヘッダファイルで、プロジェクトに含める必要があります.2.WSOCK 32.LIB:WINSOCK API接続ライブラリファイル.使用中に、必ずプロジェクトの非デフォルトの接続ライブラリとしてプロジェクトファイルに含まれます.3.WINSOCK.DLL:WINSOCKのダイナミックリンクライブラリは、WINDOWSのインストールディレクトリの下にあります.サーバー側の操作socket(ソケット)1.初期化段階においてWSAStartup()を呼び出します.この関数はアプリケーションでWindows Sockets DLLを初期化します.この関数が成功した後にのみ、アプリケーションは他のWindows Sockets DLLのAPI関数を再起動することができます.この関数をプログラムで呼び出す形式は、WSAStartup(WORD)((1<<8|1)、(LPWSADATA)&WSAData)であり、(1<<8|1)私達が使っているのはWinSockett 1.1バージョンです.WSAatはシステムから伝わったWinSocketに関する資料を記憶するために使います.2、ソケット初期化WinSockの動的な接続ライブラリを作成した後、サーバー端に監聴用のSocketを作る必要があります.そのためにSocketを呼び出すことができます.関数は、この傍受のためのソケットを作成し、このソケットに使用される通信プロトコルを定義します.この関数は、Socketオブジェクトに戻りました.失敗したらINVALDuSOCKETに戻ります.原因は、WinSocketのAPI関数はすべてこの関数を使って失敗の原因を得ることができます.SOCKET PASCAL FAR socket(proint)パラメータ:af:現在はPFuINET(AFuINET)のみを提供しています.type:Socketのタイプ(SOCK__STREAM、SOCK_uDGRAM)、protocol:通信協定(使用者が指定しない場合は0)を提供しています.確立するのがTCP/IPプロトコルに従うsocketであれば、2番目のパラメータtypeはSOCKuSTREAMとなります.のsocketは、SOCK_uDGRAMであるべきです.3、バインディングポートは次にサーバ端に定義されるこの傍受のソケットにアドレスとポートを指定します.このようにクライアントは、どのアドレスのポートに接続するべきかを知っています.そのために、私たちはbind()の函数を呼び出します.この関数が呼出されて0に戻ります.そうでなければ、SOCKET_uERRORに戻ります.(SOCKET、const struct sockaddr FAR*name、int namelen);パラメータ:s:Socketオブジェクト名、name:Socketのアドレス値は、このプログラムを実行するマシンのIPアドレスでなければなりません.namelen:nameの長さです.使用者がアドレスやポートの値を気にしない場合は、INADDR_uANY、Portが0に設定できます.Windows Socketsは自動的に適切に設定されます.のアドレスとPort(1024から5000までの値)は、その後、get sockname()関数を呼び出して、設定された値を知ることができます.4、サーバ端のSocketオブジェクトのバインディングが完了したら、サーバ端はクライアントの接続要求を受信するための待ち行列を作成しなければなりません.listen()関数は、サーバ端のソケットを傍受状態にして、確立可能な最大接続数(現在の最大値は5、最小値は1)を設定します.この関数の呼び出しは0に戻りました.そうでないと、SOCKET_uERRORに戻ります.int PASCAL FAR listen(SOCKET s、int backlogs);パラメータ:s:モニターのSocketを作成する必要があります.backlog:最大接続個数です.サーバ端のSocketがlistenを呼び出し終わったら、クライアントがconnect()関数を呼び出して接続申請を提出すると、Server端がacceptを再起動しなければなりません.このようにサーバー側とクライアント側は正式に通信プログラムの接続動作を完了します.いつクライアントが接続要求を提出するかを知るために、サーバー側のソケットが適切な時にaccept()関数を呼び出して接続の確立を完了します.WSAAcyncSelect()を使用します.関数をアクティブにして、システムに接続要求があることを知らせてくれます.この関数は0に戻りました.そうしないとSOCKET_uERRORに戻ります.int PASCAL FAR WSAAcyncSelect(SOCKET s、HWND hWnd、unsigned int wMsg、long lEvent);パラメータ:s:Socketオブジェクト;hWnd:受信メッセージのウィンドウハンドル;wMsg:ウィンドウに送信されたメッセージ;lEvent:登録されたネットワークイベント、すなわちアプリケーションがウィンドウにメッセージを送信するネットワークイベントであり、この値は下記の値FD_WRITE、FD_OOB、FDuACCEPT、FD_CONNET、FD_CLUの各組合せである.この値の具体的な意味は、FD_READ:ソケットSでデータを受信するときにメッセージを受信したいということである.FD_WRITE:ソケットSでデータを送信できるときにメッセージを受信したいということである.FDuACCEPT:ソケットSで接続要求を受信するときにメッセージを受信したいということである.FDuCONNET:ソケットSで接続成功したときにメッセージを受信したいということである.;FD OOB:ソケットSでバンド外データを受信したい場合にメッセージを受信する.具体的なアプリケーションでは、wMsgはアプリケーションで定義されたメッセージ名であるべきであり、メッセージ構造のlParamは以上の様々なネットワークイベント名である.したがって、ウィンドウでカスタマイズメッセージの処理数において、ソケットの異なるイベントに応答するために以下の構成を使用することができる.
switch(lParam){case FD READ:...break;case FD(uWRITE):...break;
5、サーバ側はクライアントの接続要求を受けて、Clientが接続要求を提出すると、Server端hwndウィンドウにWinsock Stckが私達のカスタマイズしたメッセージを送ってくれます.この時、lParamを分析して、関連する関数を呼び出してこのイベントを処理します.サーバ側にクライアントの接続要求を受けるために、accept()を使用します.この関数は、クライアントのソケットと同じように新しいソケットを作成します.これまで傍受していたソケットは引き続き傍受状態に入り、他の人の接続要求を待っています.この関数は、新たに作成されたSocketオブジェクトを返すことに成功しました.さもなければ、INVLIDuSOCKETに戻ります.SOCKET PASCSCOKET FAR accept(SCOKET、struckaddraddraddred);パラメータ:s:Socketの識別コード;addr:接続されたクライアントのアドレスを保存します.addrlen:addrの長さ6、socket接続終了サーバとクライアントとの通信接続は簡単です.このプロセスはサーバまたはクライアントのエンドから起動できます.はい、Server側のモニター状態をオフにするsocketもこの関数を利用しています.また、プログラム起動時にWSAStartupを呼び出すのに対して、プログラム終了前にWSACleeanupを呼び出す必要があります.Winsock DllがSocketによって占有されているリソースを解放することを通知します.この2つの関数はすべて呼び出しが0に戻ります.さもなければ、SOCKET_uERRORに戻ります.int PASCAL FAR closesocket(SOCKET)、パラメータ:s:Socketの識別コード;int PASCAL FAR WSAClenup(void)、パラメータ:なし
(二)実現例
サーバ端:
クライアントコード
一、原理部分
(個人的にはこの文章はいいと思いますので、ここに回します.原文の住所:http://dev.yesky.com/78/2683078.shtml)ネットワークプログラミングで最もよく使われるプログラムはCient/Server(クライアント/サーバ)モデルです.この方式では、クライアントアプリケーションはサーバプログラムにサービスを要求する.一つのサービスプログラムは、一般的によく知られているアドレスでサービスに対する要求を傍受し、つまり、サービスプロセスは、クライアントがこのサービスのアドレスに接続要求を提出するまでスリープ状態にある.この時点では、サービスプログラムは"目ざめ"され、お客様にサービスを提供します.お客様の要求に対して適切な反応をします.このようなClient/Serverモデルのネットワークプログラミングを便利にするために、90年代初めに、Microsoftが他のいくつかの会社と共同でWINDOWSの下のネットワークプログラミングインターフェース、つまりWindows Sockets規格を制定しました.これは一つのネットワークプロトコルではなく、一連の開放的で、複数のプロトコルをサポートするWindowsの下のネットワークプログラミングインターフェースです.現在のWinsockは基本的にプロトコルとは関係なくWinsockを使って様々なプロトコルの機能を呼び出すことができますが、よく使われているのはTCP/IPプロトコルです.ソケットは実際にコンピュータに通信ポートを提供しており、このポートを介して任意のソケットインターフェースを有するコンピュータと通信することができる.アプリケーションはネットワーク上で伝送され、受信した情報はこのソケットインターフェースで実現される.マイクロソフトはVisual C++のためにWinsock種類を定義しました.例えば、CAsyncSocket類とCAsyncSocketから派生したCSocket類は簡単に使えます.読者の友達はもちろんこれらの種類を使って自分のネットワークプログラムを実現できますが、Winsock APIプログラミング技術をよりよく知るために、底のAPI関数を使って簡単なWinsockネットワークアプリケーションの設計を実現する方法を検討します.それぞれServer端とClient端でSocketを操作する方法を説明し、TCP/IPに基づくデータ転送を実現し、最後に関連ソースコードを与える.VCでWINSOCKのAPIプログラミング開発を行うには、プロジェクトで次の三つのファイルを使用する必要があります.そうでないとコンパイルエラーが発生します.1.WINSOCK.H:これはWINSOCK APIのヘッダファイルで、プロジェクトに含める必要があります.2.WSOCK 32.LIB:WINSOCK API接続ライブラリファイル.使用中に、必ずプロジェクトの非デフォルトの接続ライブラリとしてプロジェクトファイルに含まれます.3.WINSOCK.DLL:WINSOCKのダイナミックリンクライブラリは、WINDOWSのインストールディレクトリの下にあります.サーバー側の操作socket(ソケット)1.初期化段階においてWSAStartup()を呼び出します.この関数はアプリケーションでWindows Sockets DLLを初期化します.この関数が成功した後にのみ、アプリケーションは他のWindows Sockets DLLのAPI関数を再起動することができます.この関数をプログラムで呼び出す形式は、WSAStartup(WORD)((1<<8|1)、(LPWSADATA)&WSAData)であり、(1<<8|1)私達が使っているのはWinSockett 1.1バージョンです.WSAatはシステムから伝わったWinSocketに関する資料を記憶するために使います.2、ソケット初期化WinSockの動的な接続ライブラリを作成した後、サーバー端に監聴用のSocketを作る必要があります.そのためにSocketを呼び出すことができます.関数は、この傍受のためのソケットを作成し、このソケットに使用される通信プロトコルを定義します.この関数は、Socketオブジェクトに戻りました.失敗したらINVALDuSOCKETに戻ります.原因は、WinSocketのAPI関数はすべてこの関数を使って失敗の原因を得ることができます.SOCKET PASCAL FAR socket(proint)パラメータ:af:現在はPFuINET(AFuINET)のみを提供しています.type:Socketのタイプ(SOCK__STREAM、SOCK_uDGRAM)、protocol:通信協定(使用者が指定しない場合は0)を提供しています.確立するのがTCP/IPプロトコルに従うsocketであれば、2番目のパラメータtypeはSOCKuSTREAMとなります.のsocketは、SOCK_uDGRAMであるべきです.3、バインディングポートは次にサーバ端に定義されるこの傍受のソケットにアドレスとポートを指定します.このようにクライアントは、どのアドレスのポートに接続するべきかを知っています.そのために、私たちはbind()の函数を呼び出します.この関数が呼出されて0に戻ります.そうでなければ、SOCKET_uERRORに戻ります.(SOCKET、const struct sockaddr FAR*name、int namelen);パラメータ:s:Socketオブジェクト名、name:Socketのアドレス値は、このプログラムを実行するマシンのIPアドレスでなければなりません.namelen:nameの長さです.使用者がアドレスやポートの値を気にしない場合は、INADDR_uANY、Portが0に設定できます.Windows Socketsは自動的に適切に設定されます.のアドレスとPort(1024から5000までの値)は、その後、get sockname()関数を呼び出して、設定された値を知ることができます.4、サーバ端のSocketオブジェクトのバインディングが完了したら、サーバ端はクライアントの接続要求を受信するための待ち行列を作成しなければなりません.listen()関数は、サーバ端のソケットを傍受状態にして、確立可能な最大接続数(現在の最大値は5、最小値は1)を設定します.この関数の呼び出しは0に戻りました.そうでないと、SOCKET_uERRORに戻ります.int PASCAL FAR listen(SOCKET s、int backlogs);パラメータ:s:モニターのSocketを作成する必要があります.backlog:最大接続個数です.サーバ端のSocketがlistenを呼び出し終わったら、クライアントがconnect()関数を呼び出して接続申請を提出すると、Server端がacceptを再起動しなければなりません.このようにサーバー側とクライアント側は正式に通信プログラムの接続動作を完了します.いつクライアントが接続要求を提出するかを知るために、サーバー側のソケットが適切な時にaccept()関数を呼び出して接続の確立を完了します.WSAAcyncSelect()を使用します.関数をアクティブにして、システムに接続要求があることを知らせてくれます.この関数は0に戻りました.そうしないとSOCKET_uERRORに戻ります.int PASCAL FAR WSAAcyncSelect(SOCKET s、HWND hWnd、unsigned int wMsg、long lEvent);パラメータ:s:Socketオブジェクト;hWnd:受信メッセージのウィンドウハンドル;wMsg:ウィンドウに送信されたメッセージ;lEvent:登録されたネットワークイベント、すなわちアプリケーションがウィンドウにメッセージを送信するネットワークイベントであり、この値は下記の値FD_WRITE、FD_OOB、FDuACCEPT、FD_CONNET、FD_CLUの各組合せである.この値の具体的な意味は、FD_READ:ソケットSでデータを受信するときにメッセージを受信したいということである.FD_WRITE:ソケットSでデータを送信できるときにメッセージを受信したいということである.FDuACCEPT:ソケットSで接続要求を受信するときにメッセージを受信したいということである.FDuCONNET:ソケットSで接続成功したときにメッセージを受信したいということである.;FD OOB:ソケットSでバンド外データを受信したい場合にメッセージを受信する.具体的なアプリケーションでは、wMsgはアプリケーションで定義されたメッセージ名であるべきであり、メッセージ構造のlParamは以上の様々なネットワークイベント名である.したがって、ウィンドウでカスタマイズメッセージの処理数において、ソケットの異なるイベントに応答するために以下の構成を使用することができる.
switch(lParam){case FD READ:...break;case FD(uWRITE):...break;
5、サーバ側はクライアントの接続要求を受けて、Clientが接続要求を提出すると、Server端hwndウィンドウにWinsock Stckが私達のカスタマイズしたメッセージを送ってくれます.この時、lParamを分析して、関連する関数を呼び出してこのイベントを処理します.サーバ側にクライアントの接続要求を受けるために、accept()を使用します.この関数は、クライアントのソケットと同じように新しいソケットを作成します.これまで傍受していたソケットは引き続き傍受状態に入り、他の人の接続要求を待っています.この関数は、新たに作成されたSocketオブジェクトを返すことに成功しました.さもなければ、INVLIDuSOCKETに戻ります.SOCKET PASCSCOKET FAR accept(SCOKET、struckaddraddraddred);パラメータ:s:Socketの識別コード;addr:接続されたクライアントのアドレスを保存します.addrlen:addrの長さ6、socket接続終了サーバとクライアントとの通信接続は簡単です.このプロセスはサーバまたはクライアントのエンドから起動できます.はい、Server側のモニター状態をオフにするsocketもこの関数を利用しています.また、プログラム起動時にWSAStartupを呼び出すのに対して、プログラム終了前にWSACleeanupを呼び出す必要があります.Winsock DllがSocketによって占有されているリソースを解放することを通知します.この2つの関数はすべて呼び出しが0に戻ります.さもなければ、SOCKET_uERRORに戻ります.int PASCAL FAR closesocket(SOCKET)、パラメータ:s:Socketの識別コード;int PASCAL FAR WSAClenup(void)、パラメータ:なし
(二)実現例
サーバ端:
#include
<
stdio.h
>
#include
<
Winsock2.h
>
#pragma
comment(lib, "ws2_32.lib")
void
main()
{
WORD wVersionRequested;
WSADATA wsaData;
int
err;
wVersionRequested
=
MAKEWORD(
1
,
1
);
err
=
WSAStartup( wVersionRequested,
&
wsaData );
if
( err
!=
0
) {
return
;
}
if
( LOBYTE( wsaData.wVersion )
!=
1
||
HIBYTE( wsaData.wVersion )
!=
1
) {
WSACleanup( );
return
;
}
SOCKET sockSrv
=
socket(AF_INET,SOCK_STREAM,
0
);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr
=
htonl(INADDR_ANY);
addrSrv.sin_family
=
AF_INET;
addrSrv.sin_port
=
htons(
6000
);
bind(sockSrv,(SOCKADDR
*
)
&
addrSrv,
sizeof
(SOCKADDR));
//
listen(sockSrv,
5
);
SOCKADDR_IN addrClient;
//
ip
int
len
=
sizeof
(SOCKADDR);
while
(
1
)
{
SOCKET sockConn
=
accept(sockSrv,(SOCKADDR
*
)
&
addrClient,
&
len);
//
, ip
char
sendBuf[
50
];
sprintf(sendBuf,
"
Welcome %s to here!
"
,inet_ntoa(addrClient.sin_addr));
//
send(sockConn,sendBuf,strlen(sendBuf)
+
1
,
0
);
//
char
recvBuf[
50
];
recv(sockConn,recvBuf,
50
,
0
);
//
printf(
"
%s
"
,recvBuf);
//
closesocket(sockConn);
//
}
}
クライアントコード
#include
<
stdio.h
>
#include
<
Winsock2.h
>
#pragma
comment(lib, "ws2_32.lib")
void
main()
{
WORD wVersionRequested;
WSADATA wsaData;
//
WSAata WinSocket 。
int
err;
wVersionRequested
=
MAKEWORD(
1
,
1
);
err
=
WSAStartup( wVersionRequested,
&
wsaData );
if
( err
!=
0
) {
return
;
}
if
( LOBYTE( wsaData.wVersion )
!=
1
||
HIBYTE( wsaData.wVersion )
!=
1
)
{
WSACleanup( );
return
;
}
SOCKET sockClient
=
socket(AF_INET,SOCK_STREAM,
0
);
//
AF_INET ..tcp
//
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr
=
inet_addr(
"
127.0.0.1
"
);// ,
addrSrv.sin_family
=
AF_INET;
addrSrv.sin_port
=
htons(
6000
);
//
connect(sockClient,(SOCKADDR
*
)
&
addrSrv,
sizeof
(SOCKADDR));
//
char
recvBuf[
50
];
recv(sockClient,recvBuf,
50
,
0
);
//
printf(
"
%s
"
,recvBuf);
send(sockClient,
"
hello
"
,strlen(
"
hello
"
)
+
1
,
0
);
//
closesocket(sockClient);
//
WSACleanup();
}