説明:メインサブステップの例は、WindowsプラットフォームのプログラミングTCPソケットが与えられ、仕様WINDOWS Winsockのネットワーク通信を使用して、ネットワークプログラミング、各部分の詳細手順を説明するため。
転送ソケットSOCK_STREAM SOCK_DGRAM SOCK_RAWの3種類がありますが、
特に参照:https://blog.csdn.net/bjyddxhfxq/article/details/51119653
ソースのフルバージョンのダウンロード:https://download.csdn.net/download/ckzhb/10601058
記事のディレクトリ
まず、サーバ
機能:クライアントの要求を待って、ポートを監視し、成功した接続が確立され、サーバは毎回入力されたデータを、データのグループを送信するには、入力されたQ場合、送信を停止します。
1、ソケットの作成、ソケットライブラリをロードします。
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib") //静态加入一个lib文件
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0) //WSAStartup返回0表示设置初始化成功
return 0;
/*创建套接字*/
//AF_INET表示IPv4,SOCK_STREAM数据传输方式,IPPROTO_TCP传输协议;
SOCKET listenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (listenSocket == INVALID_SOCKET)
{
printf("套接字创建失败");
WSACleanup();
return 0;
}
説明:
- Microsoft WordのSDK 16ビット符号なし整数; WSADATAが構造体です。
- MAKEWORD(b)は、ここでWinsockのバージョンを指定するために使用されるマクロです。
- WSAStartupを、すなわち、WSA(Windowsソケット非同期、Windowsの非同期ソケット)は、コマンドを起動し、WSAStartupのは、最初のアプリケーションやWindowsソケットDLL関数の呼び出しでなければなりません。これは、アプリケーションまたはDLLのバージョン番号はWindowsソケットAPIを示し、特定のWindowsソケットの実装の詳細を取得できます。アプリケーションまたはDLLは、のみ()呼び出しの後にさらにWindowsソケットAPI関数の呼び出し前に成功したWSAStartupをすることができます。
- 機能ソケット()は、ソケット()関数は、ソケット記述子と指定されたアドレスファミリー、タイプおよびプロトコルのデータに使用されるリソースを割り当てるために使用され、エラーが発生しない場合は、ソケット()は新しいソケットを説明するための参照を返します言葉。それ以外の場合は、INVALID_SOCKETエラーを返します。
2、バインドIPアドレスとポートへのソケット
/*绑定IP和端口*/
//配置监听地址和端口
sockaddr_in addrListen;
addrListen.sin_family = AF_INET; //指定IP格式
addrListen.sin_port = htons(8888); //绑定端口号
addrListen.sin_addr.S_un.S_addr = INADDR_ANY; //表示任何IP service.sin_addr.s_addr = inet_addr("127.0.0.1");
if (bind(listenSocket, (SOCKADDR*)&addrListen, sizeof(addrListen)) == SOCKET_ERROR) //(SOCKADDR*)
{
printf("绑定失败");
closesocket(listenSocket);
return 0;
}
説明:
- sockaddr_inはデータ構造である、アドレスを示すパラメータDO結合、接続、のrecvfrom、のsendto他の機能、情報。
- バインド()函数int型バインド(int型数sockfd、constの構造体のsockaddr * my_addr、のsocklen_t addrlenは)。
バインド()関数は、ソケットインタフェースを作成するために結合することによってアドレスを割り当てます。
3、指定したポートでリスニング
/*开始监听*/
if (listen(listenSocket, 5) == SOCKET_ERROR)
{
printf("监听出错");
closesocket(listenSocket);
return 0;
}
説明:
- (int型の数sockfd、int型のバックログを)聞くINT。
- 数sockfd:識別バンドルされたソケット記述子が接続されていません。
- バックログ:接続キューの最大長を待ちます。
図4に示すように、要求は、対応するソケットへの接続の確立を受信した場合、クライアントの要求を待っています
/*等待连接,连接后建立一个新的套接字*/
SOCKET revSocket; //对应此时所建立连接的套接字的句柄
sockaddr_in remoteAddr; //接收连接到服务器上的地址信息
int remoteAddrLen = sizeof(remoteAddr);
printf("等待连接...\n");
/*等待客户端请求,服务器接收请求*/
revSocket = accept(listenSocket, (SOCKADDR*)&remoteAddr, &remoteAddrLen); //等待客户端接入,直到有客户端连接上来为止
if (revSocket == INVALID_SOCKET)
{
printf("客户端发出请求,服务器接收请求失败:\n",WSAGetLastError());
closesocket(listenSocket);
WSACleanup();
return 0;
}
else
{
printf("客服端与服务器建立连接成功:%s \n", inet_ntoa(remoteAddr.sin_addr));
}
説明:
- まず、ソケットを使用して、ソケットが以前、データ伝送とは異なることを新しいソケット、ノートを定義します。
- ソケットが受け入れる(int型の数sockfdが、構造体のsockaddr * addrは、のsocklen_t * addrlenは)。
ソケットとリターンハンドルの新しい種類を作成し、第一コネクタ待ちキューからコネクターを抽出する機能。
- 数sockfd:ソケット記述、聞くの聴取ソケットコネクタ(リア)。
- ADDR :(オプション)受信エンティティは、接続された通信層技術のアドレスであることを特徴とする請求バッファへのポインタ。パラメータの実際の形式は、ADDRアドレスファミリのソケットを生成作成さによって決定されます。
- addrlenは:(オプション)ポインタ、入力パラメータ、ADDRと一緒に使用、ポイントアドレスaddr長整数そこ。
5、クライアントがデータを受信し、
char revData[255] = "";
char *sendData = new char[100];
/*通过建立的连接进行通信*/
int res = recv(revSocket, revData, 255, 0);
if (res > 0)
{
printf("Bytes received: %d\n", res);
printf("客户端发送的数据: %s\n", revData);
}
else if (res == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
説明:
INTのRECV(LEN SOCKET s、CHAR FAR * bufは、INT、INTフラグ)。
クライアントまたはサーバアプリケーションがTCP接続recv関数の他端からデータを受信したか否かを、戻り値は、受信条件データに応じて決定されます。
- S:指定受信側のソケット記述子。
- BUFは:recv関数を受けたデータを格納するのに使用されるバッファを示します。
- LEN:BUFの指定された長さ。
- フラグ:Sは、典型的には0です。
図6は、クライアントにデータを送信します
while (cin>>sendData)
{
//cout << strlen(sendData) << endl;
if (strcmp(sendData, "q") == 0)
{
printf("服务器停止发送数据!\n");
break;
}
//发送数据
send(revSocket, sendData, strlen(sendData), 0);
}
説明:
int型送信(SOCKET s、constのchar型FAR * bufに、int型のlen、int型のフラグ);
基本的に同様のrecv()関数を意味します。
7、ソケットが閉じている、クローズロードされたソケットライブラリ
closesocket(listenSocket);
WSACleanup();
第二に、クライアント
関数は、サーバーの一部と同じであり、別途記載されていません!
1、ソケットを作成し、ソケットライブラリをロード
WORD sockVerson = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVerson, &wsaData) != 0)
return 0;
//建立客户端socket
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET)
{
printf("套接字创建失败");
WSACleanup();
return 0;
}
2、サーバへの接続要求を発行
//定义要连接的服务器地址
sockaddr_in addrConServer;
addrConServer.sin_family = AF_INET;
addrConServer.sin_port = htons(8888);
addrConServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (connect(clientSocket, (SOCKADDR*)&addrConServer, sizeof(addrConServer)) == SOCKET_ERROR)
{
printf("客户端建立连接失败!\n");
closesocket(clientSocket);
WSACleanup();
return 0;
}
else
printf("客户端建立连接成功,准备发送数据!\n");
説明:
int型接続(SOCKET s、constの構造体のsockaddr *名、int型NAMELEN)。
この機能は、フロータイプのソケット(SOCK_STREAMタイプ)のための指定された外部ポート接続を作成し、リモートホストとの接続を確立するための名前の使用は、ソケットに成功したリターン・コールと、それがデータを受信または送信することができます。データグラムソケットタイプ(SOCK_DGRAMタイプ)の場合、デフォルトの宛先アドレスに設定され、その後の送信(のためにそれを使用)し、RECV()の呼び出し。
サーバ間のデータ伝送のための3、及び
//发送数据
int sendRes = send(clientSocket, sendBuf, (int)strlen(sendBuf), 0);
if (sendRes == SOCKET_ERROR)
{
printf("客户端send()出现错误 : %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
return 0;
}
else
printf("客户端发送数据成功!\n");
//接收服务端数据
/*通过建立的连接进行通信*/
do
{
char revSerData[100] = "";
res = recv(clientSocket, revSerData, sizeof(revSerData), 0);
if (res > 0)
{
printf("Bytes received: %d\n", res);
printf("服务器发送的数据: %s\n", revSerData);
}
else if (res == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (res > 0);
4ソケットがクローズされ、クローズロードされたソケットライブラリ
closesocket(clientSocket);
WSACleanup();
第三に、営業成績
最初のサーバーを実行して、クライアントを実行します。
次に、入力データは、目的サーバに送信されます。