C++ネットワークプログラミング学習:ネットワークデータメッセージの送受信
ネットワークプログラミング学習レコード使用言語はC/C+ ソースコードサポートプラットフォームは、Windows 笔记一:基础TCP服务端/クライアント 点我跳转笔记二:ネットワークデータメッセージの送受信 点我跳转笔记三:selectネットワークモデル 点我跳转笔记四:プラットフォームをまたいでWindowsをサポート、Linuxシステム 点我跳转笔记5:ソースコードのパッケージ 点我跳转笔记6:バッファオーバーフローと粘着包分包 点我跳转笔记7:サービス端マルチスレッド分离业务処理高负荷 点我跳转笔记
ノート2ネットワークプログラミング学習記録 一、ネットワークデータメッセージのフォーマット定義 二、パケットヘッダとパケットデータを別々に送受信 1.要約 2.コードおよびその詳細なコメント 2.1サービス側コード 2.2クライアントコード
三、分割送受信メッセージデータを一次送受信に変更 1.構想 2.コードおよびその詳細なコメント 2.1サービス側コード 2.2クライアントコード
一、ネットワークデータメッセージのフォーマット定義メッセージには2つの部分があり、パケットヘッダとパケットは、ネットワークメッセージの基本ユニットである. ヘッダ:今回のメッセージパケットのサイズを記述し、パケットデータの役割を記述する. パッケージ:転送する必要があるデータが含まれています.
このデータ構造によれば,パケットヘッダの内容に基づいて,パケット体のデータを柔軟に処理することができる.
二、包頭と包体データを別々に送受する
1.概括
上記のネットワークデータメッセージの定義を通じて、簡単に考えることができます.送信側は2回のsend操作を行い、1回目のsendはパケットヘッダを送信し、2回目のsendはパケット体を送信し、ネットワークデータメッセージの送信を実現することができる. 受信側は2回のrecv操作を行い、1回目のrecvはパケットヘッダを受信し、2回目のrecvはパケット体を受信し、パケットヘッダの内容に基づいてデータ処理を行い、ネットワークデータメッセージの受信を実現することができる.
以上の操作により、ネットワークデータメッセージの送受信を実現できます.
2.コードとその詳細なコメント
2.1サービス側コード
2.2クライアントコード
三、別々に送受信するメッセージデータを一回の送受信に変更する
1.考え方
上記より,send 2回とrecv 2回でメッセージの送受信が可能であることが分かるが,操作が面倒であり,DateHeaderヘッダ構造体を複数回宣言する必要があり,時間リソースを消費するだけでなく,エラーも発生しやすい.したがって,別々の送受信を1回の送受信に変更することを試みることができる.大まかな考え方は,メッセージの構造体を完備させ,パケットにヘッダ構造体を継承させたり,パケット構造体にパケットヘッダ構造体を1つ含ませたりすることである.これにより,メッセージの構造体を整備し,send操作を1回だけ行えば,すべてのメッセージデータを送信できる. データ受信を行う場合、まずパケットヘッダサイズのデータを受信し、その後、パケットヘッダの内容に基づいて、次に受信するデータのサイズ、すなわち、受信総データサイズからパケットヘッダデータサイズを減算したデータを決定する.次にrecvを用いて残りのデータを受信する場合は,ポインタオフセットを用いて構造体パケットヘッダの受信(受信したため)をスキップし,パケットデータ位置に直接受信する.
2.コードとその詳細なコメント
2.1サービス側コード
2.2クライアントコード
ノート2
一、ネットワークデータメッセージのフォーマット定義
このデータ構造によれば,パケットヘッダの内容に基づいて,パケット体のデータを柔軟に処理することができる.
二、包頭と包体データを別々に送受する
1.概括
上記のネットワークデータメッセージの定義を通じて、簡単に考えることができます.
以上の操作により、ネットワークデータメッセージの送受信を実現できます.
2.コードとその詳細なコメント
2.1サービス側コード
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")// windows
using namespace std;
//
enum cmd
{
CMD_LOGIN,//
CMD_LOGOUT,//
CMD_ERROR//
};
//
struct DateHeader
{
short cmd;//
short date_length;//
};
// 1
struct Login
{
char UserName[32];//
char PassWord[32];//
};
// 2
struct LoginResult
{
int Result;
};
// 3
struct Logout
{
char UserName[32];//
};
// 4
struct LogoutResult
{
int Result;
};
int main()
{
// windows socket 2,x windows
WORD ver = MAKEWORD(2,2);//WinSock
WSADATA dat;// WSAStartup Socket
if(0 != WSAStartup(ver,&dat))// 0
{
return 0;
}
// socket
SOCKET _mysocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//IPV4 TCP
if(INVALID_SOCKET == _mysocket)//
{
return 0;
}
// IP
sockaddr_in _myaddr = {
};// sockaddr sockaddr_in
_myaddr.sin_family = AF_INET;//IPV4
_myaddr.sin_port = htons(8888);// host to net unsigned short
_myaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");// INADDR_ANY
if(SOCKET_ERROR == bind(_mysocket,(sockaddr*)&_myaddr,sizeof(sockaddr_in)))//socket ( )sockaddr
{
cout<<" "<<endl;
}
else
{
//cout<
}
//
if(SOCKET_ERROR == listen(_mysocket,5))//
{
cout<<" "<<endl;
}
else
{
//cout<
}
//
sockaddr_in _clientAddr = {
};// sockadd
int _addr_len = sizeof(sockaddr_in);// sockadd
SOCKET _temp_socket = INVALID_SOCKET;//
_temp_socket = accept(_mysocket,(sockaddr*)&_clientAddr,&_addr_len);//
if(INVALID_SOCKET == _temp_socket)//
{
cout<<" Socket"<<endl;
}
else
{
cout<<" "<<endl;
printf("IP :%s
", inet_ntoa(_clientAddr.sin_addr));
}
while(true)
{
//
DateHeader _head = {
};
int _buf_len = recv(_temp_socket,(char*)&_head,sizeof(DateHeader),0);
if(_buf_len<=0)
{
printf("
");
break;
}
printf(" , :%d, :%d
",_head.cmd,_head.date_length);
switch(_head.cmd)
{
case CMD_LOGIN://
{
Login _login = {
};
recv(_temp_socket,(char*)&_login,sizeof(Login),0);
/*
*/
printf("%s
",_login.UserName);
send(_temp_socket,(char*)&_head,sizeof(DateHeader),0);//
LoginResult _result = {
1};
send(_temp_socket,(char*)&_result,sizeof(LoginResult),0);//
}
break;
case CMD_LOGOUT://
{
Logout _logout = {
};
recv(_temp_socket,(char*)&_logout,sizeof(Logout),0);
/*
*/
printf("%s
",_logout.UserName);
send(_temp_socket,(char*)&_head,sizeof(DateHeader),0);//
LogoutResult _result = {
1};
send(_temp_socket,(char*)&_result,sizeof(LogoutResult),0);//
}
break;
default://
{
_head.cmd = CMD_ERROR;
_head.date_length = 0;
send(_temp_socket,(char*)&_head,sizeof(DateHeader),0);//
}
break;
}
}
// socket
closesocket(_temp_socket);
// socket
closesocket(_mysocket);
// windows socket
WSACleanup();
printf(" , ");
getchar();
return 0;
}
2.2クライアントコード
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")// windows
using namespace std;
//
enum cmd
{
CMD_LOGIN,//
CMD_LOGOUT,//
CMD_ERROR//
};
//
struct DateHeader
{
short cmd;//
short date_length;//
};
// 1
struct Login
{
char UserName[32];//
char PassWord[32];//
};
// 2
struct LoginResult
{
int Result;
};
// 3
struct Logout
{
char UserName[32];//
};
// 4
struct LogoutResult
{
int Result;
};
int main()
{
// windows socket 2,x windows
WORD ver = MAKEWORD(2,2);//WinSock
WSADATA dat;// WSAStartup Socket
if(0 != WSAStartup(ver,&dat))// 0
{
return 0;
}
// socket
SOCKET _mysocket = socket(AF_INET,SOCK_STREAM,0);//IPV4
if(INVALID_SOCKET == _mysocket)//
{
return 0;
}
//
sockaddr_in _sin = {
};//sockaddr
_sin.sin_family = AF_INET;//IPV4
_sin.sin_port = htons(8888);//
_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");// IP
if(SOCKET_ERROR == connect(_mysocket,(sockaddr*)&_sin,sizeof(sockaddr_in)))
{
cout<<" "<<endl;
closesocket(_mysocket);
}
else
{
cout<<" "<<endl;
}
while(true)
{
//
char _msg[256] = {
};
scanf("%s",_msg);
//
if(0 == strcmp(_msg,"exit"))
{
break;
}
else if(0 == strcmp(_msg,"login"))
{
//
Login _login = {
" ","123456"};
DateHeader _head = {
CMD_LOGIN,sizeof(_login)};
send(_mysocket,(const char*)&_head,sizeof(_head),0);
send(_mysocket,(const char*)&_login,sizeof(_login),0);
//
DateHeader _head2 = {
};
LoginResult _result= {
};
recv(_mysocket,(char*)&_head2,sizeof(DateHeader),0);
recv(_mysocket,(char*)&_result,sizeof(LoginResult),0);
printf("result:%d
",_result.Result);
}
else if(0 == strcmp(_msg,"logout"))
{
//
Logout _logout = {
" "};
DateHeader _head = {
CMD_LOGOUT,sizeof(_logout)};
send(_mysocket,(const char*)&_head,sizeof(_head),0);
send(_mysocket,(const char*)&_logout,sizeof(_logout),0);
//
DateHeader _head2 = {
};
LogoutResult _result= {
};
recv(_mysocket,(char*)&_head2,sizeof(DateHeader),0);
recv(_mysocket,(char*)&_result,sizeof(LogoutResult),0);
printf("result:%d
",_result.Result);
}
else
{
printf("
");
}
}
// socket
closesocket(_mysocket);
// windows socket
WSACleanup();
return 0;
}
三、別々に送受信するメッセージデータを一回の送受信に変更する
1.考え方
上記より,send 2回とrecv 2回でメッセージの送受信が可能であることが分かるが,操作が面倒であり,DateHeaderヘッダ構造体を複数回宣言する必要があり,時間リソースを消費するだけでなく,エラーも発生しやすい.したがって,別々の送受信を1回の送受信に変更することを試みることができる.大まかな考え方は,メッセージの構造体を完備させ,パケットにヘッダ構造体を継承させたり,パケット構造体にパケットヘッダ構造体を1つ含ませたりすることである.これにより,メッセージの構造体を整備し,send操作を1回だけ行えば,すべてのメッセージデータを送信できる. データ受信を行う場合、まずパケットヘッダサイズのデータを受信し、その後、パケットヘッダの内容に基づいて、次に受信するデータのサイズ、すなわち、受信総データサイズからパケットヘッダデータサイズを減算したデータを決定する.次にrecvを用いて残りのデータを受信する場合は,ポインタオフセットを用いて構造体パケットヘッダの受信(受信したため)をスキップし,パケットデータ位置に直接受信する.
/*
:&_login+sizeof(DateHeader)
:sizeof(Login)-sizeof(DateHeader)
*/
recv(_temp_socket,(char*)&_login+sizeof(DateHeader),sizeof(Login)-sizeof(DateHeader),0);
2.コードとその詳細なコメント
2.1サービス側コード
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")// windows
using namespace std;
//
enum cmd
{
CMD_LOGIN,//
CMD_LOGINRESULT,//
CMD_LOGOUT,//
CMD_LOGOUTRESULT,//
CMD_ERROR//
};
//
struct DateHeader
{
short cmd;//
short date_length;//
};
// 1
struct Login : public DateHeader
{
Login()//
{
this->cmd = CMD_LOGIN;
this->date_length = sizeof(Login);
}
char UserName[32];//
char PassWord[32];//
};
// 2
struct LoginResult : public DateHeader
{
LoginResult()//
{
this->cmd = CMD_LOGINRESULT;
this->date_length = sizeof(LoginResult);
}
int Result;
};
// 3
struct Logout : public DateHeader
{
Logout()//
{
this->cmd = CMD_LOGOUT;
this->date_length = sizeof(Logout);
}
char UserName[32];//
};
// 4
struct LogoutResult : public DateHeader
{
LogoutResult()//
{
this->cmd = CMD_LOGOUTRESULT;
this->date_length = sizeof(LogoutResult);
}
int Result;
};
int main()
{
// windows socket 2,x windows
WORD ver = MAKEWORD(2,2);//WinSock
WSADATA dat;// WSAStartup Socket
if(0 != WSAStartup(ver,&dat))// 0
{
return 0;
}
// socket
SOCKET _mysocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//IPV4 TCP
if(INVALID_SOCKET == _mysocket)//
{
return 0;
}
// IP
sockaddr_in _myaddr = {
};// sockaddr sockaddr_in
_myaddr.sin_family = AF_INET;//IPV4
_myaddr.sin_port = htons(8888);// host to net unsigned short
_myaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");// INADDR_ANY
if(SOCKET_ERROR == bind(_mysocket,(sockaddr*)&_myaddr,sizeof(sockaddr_in)))//socket ( )sockaddr
{
cout<<" "<<endl;
}
else
{
//cout<
}
//
if(SOCKET_ERROR == listen(_mysocket,5))//
{
cout<<" "<<endl;
}
else
{
//cout<
}
//
sockaddr_in _clientAddr = {
};// sockadd
int _addr_len = sizeof(sockaddr_in);// sockadd
SOCKET _temp_socket = INVALID_SOCKET;//
_temp_socket = accept(_mysocket,(sockaddr*)&_clientAddr,&_addr_len);//
if(INVALID_SOCKET == _temp_socket)//
{
cout<<" Socket"<<endl;
}
else
{
cout<<" "<<endl;
printf("IP :%s
", inet_ntoa(_clientAddr.sin_addr));
}
while(true)
{
//
DateHeader _head = {
};
int _buf_len = recv(_temp_socket,(char*)&_head,sizeof(DateHeader),0);
if(_buf_len<=0)
{
printf("
");
break;
}
printf(" , :%d, :%d
",_head.cmd,_head.date_length);
switch(_head.cmd)
{
case CMD_LOGIN://
{
Login _login;
recv(_temp_socket,(char*)&_login+sizeof(DateHeader),sizeof(Login)-sizeof(DateHeader),0);
/*
*/
printf("%s
:%s
",_login.UserName,_login.PassWord);
LoginResult _result;
_result.Result = 1;
send(_temp_socket,(char*)&_result,sizeof(LoginResult),0);//
}
break;
case CMD_LOGOUT://
{
Logout _logout;
recv(_temp_socket,(char*)&_logout+sizeof(DateHeader),sizeof(Logout)-sizeof(DateHeader),0);
/*
*/
printf("%s
",_logout.UserName);
LogoutResult _result;
_result.Result = 1;
send(_temp_socket,(char*)&_result,sizeof(LogoutResult),0);//
}
break;
default://
{
_head.cmd = CMD_ERROR;
_head.date_length = 0;
send(_temp_socket,(char*)&_head,sizeof(DateHeader),0);//
}
break;
}
}
// socket
closesocket(_temp_socket);
// socket
closesocket(_mysocket);
// windows socket
WSACleanup();
printf(" , ");
getchar();
return 0;
}
2.2クライアントコード
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")// windows
using namespace std;
//
enum cmd
{
CMD_LOGIN,//
CMD_LOGINRESULT,//
CMD_LOGOUT,//
CMD_LOGOUTRESULT,//
CMD_ERROR//
};
//
struct DateHeader
{
short cmd;//
short date_length;//
};
// 1
struct Login : public DateHeader
{
Login()//
{
this->cmd = CMD_LOGIN;
this->date_length = sizeof(Login);
}
char UserName[32];//
char PassWord[32];//
};
// 2
struct LoginResult : public DateHeader
{
LoginResult()//
{
this->cmd = CMD_LOGINRESULT;
this->date_length = sizeof(LoginResult);
}
int Result;
};
// 3
struct Logout : public DateHeader
{
Logout()//
{
this->cmd = CMD_LOGOUT;
this->date_length = sizeof(Logout);
}
char UserName[32];//
};
// 4
struct LogoutResult : public DateHeader
{
LogoutResult()//
{
this->cmd = CMD_LOGOUTRESULT;
this->date_length = sizeof(LogoutResult);
}
int Result;
};
int main()
{
// windows socket 2,x windows
WORD ver = MAKEWORD(2,2);//WinSock
WSADATA dat;// WSAStartup Socket
if(0 != WSAStartup(ver,&dat))// 0
{
return 0;
}
// socket
SOCKET _mysocket = socket(AF_INET,SOCK_STREAM,0);//IPV4
if(INVALID_SOCKET == _mysocket)//
{
return 0;
}
//
sockaddr_in _sin = {
};//sockaddr
_sin.sin_family = AF_INET;//IPV4
_sin.sin_port = htons(8888);//
_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");// IP
if(SOCKET_ERROR == connect(_mysocket,(sockaddr*)&_sin,sizeof(sockaddr_in)))
{
cout<<" "<<endl;
closesocket(_mysocket);
}
else
{
cout<<" "<<endl;
}
while(true)
{
//
char _msg[256] = {
};
scanf("%s",_msg);
//
if(0 == strcmp(_msg,"exit"))
{
break;
}
else if(0 == strcmp(_msg,"login"))
{
//
Login _login;
strcpy(_login.UserName," ");
strcpy(_login.PassWord,"123456");
send(_mysocket,(const char*)&_login,sizeof(_login),0);
//
LoginResult _result;
recv(_mysocket,(char*)&_result,sizeof(LoginResult),0);
printf("result:%d
",_result.Result);
}
else if(0 == strcmp(_msg,"logout"))
{
//
Logout _logout;
strcpy(_logout.UserName," ");
send(_mysocket,(const char*)&_logout,sizeof(_logout),0);
//
LogoutResult _result;
recv(_mysocket,(char*)&_result,sizeof(LogoutResult),0);
printf("result:%d
",_result.Result);
}
else
{
printf("
");
}
}
// socket
closesocket(_mysocket);
// windows socket
WSACleanup();
return 0;
}