流式套接字程式設計多線程通信
環境:VS2017
首先,附上原作者的文章連結:
作者:弱菜zc
來源:CSDN
原文:https ://blog.csdn.net/zchahaha/article/details/56831242
版權聲明:本文為部落客原創文章,轉載請附上博文連結!
建立一個控制台應用程式 ,建立一個解決方案,當然,建立應用程式的時候已經幫你建立好了解決方案,建立兩個項目,一個放伺服器,一個放用戶端。
網絡程式設計:TCP流式套接字多線程通信流式套接字程式設計多線程通信
網絡程式設計:TCP流式套接字多線程通信流式套接字程式設計多線程通信 代碼區:(注意:伺服器和用戶端的IP都是使用回環位址,如果隻是在本地運作,改為自己本機的IP就行了)
伺服器:
#include"pch.h"
#include <iostream>
#include <winsock2.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
#define PORT 4000
#define IP_ADDRESS "127.0.0.1"
DWORD WINAPI ClientThread(LPVOID lpParameter)
{
struct sockaddr_in ClientAddr;
int AddrLen = sizeof(ClientAddr);
SOCKET CientSocket = (SOCKET)lpParameter;
int Ret = 0;
char RecvBuffer[MAX_PATH];
while (true)
{
memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
Ret = recv(CientSocket, RecvBuffer, MAX_PATH, 0);
getpeername(CientSocket, (struct sockaddr *)&ClientAddr, &AddrLen);
if (Ret == 0 || Ret == SOCKET_ERROR)
{
cout << "客戶" << inet_ntoa(ClientAddr.sin_addr) << ":" << ClientAddr.sin_port << "退出。" << endl;//用戶端退出
break;
}
cout << "客戶" << inet_ntoa(ClientAddr.sin_addr) << ":" << ClientAddr.sin_port << "說:" << RecvBuffer << endl;//輸出服務端收到的資訊
Ret = send(CientSocket, RecvBuffer, (int)strlen(RecvBuffer), 0);//将接收到的字元串回送給用戶端
}
return 0;
}
int main(int argc, char* argv[])
{
WSADATA Ws;
SOCKET ServerSocket, ClientSocket;
struct sockaddr_in LocalAddr, ClientAddr;
int Ret = 0;
int AddrLen = 0;
HANDLE hThread = NULL;
//Init Windows Socket
if (WSAStartup(MAKEWORD(2, 2), &Ws) != 0)
{
cout << "Init Windows Socket Failed::" << GetLastError() << endl;
return -1;
}
//Create Socket
ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ServerSocket == INVALID_SOCKET)
{
cout << "Create Socket Failed::" << GetLastError() << endl;
return -1;
}
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
LocalAddr.sin_port = htons(PORT);
memset(LocalAddr.sin_zero, 0x00, 8);
//Bind Socket
Ret = bind(ServerSocket, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr));
if (Ret != 0)
{
cout << "Bind Socket Failed::" << GetLastError() << endl;
return -1;
}
//listen
Ret = listen(ServerSocket, 10);
if (Ret != 0)
{
cout << "listen Socket Failed::" << GetLastError() << endl;
return -1;
}
cout << "服務端已經啟動" << endl;
while (true)
{
AddrLen = sizeof(ClientAddr);
ClientSocket = accept(ServerSocket, (struct sockaddr*)&ClientAddr, &AddrLen);
if (ClientSocket == INVALID_SOCKET)
{
cout << "Accept Failed::" << GetLastError() << endl;
break;
}
cout << "用戶端連接配接::" << inet_ntoa(ClientAddr.sin_addr) << ":" << ClientAddr.sin_port << endl;
hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)ClientSocket, 0, NULL);
if (hThread == NULL)
{
cout << "Create Thread Failed!" << endl;
break;
}
CloseHandle(hThread);
}
closesocket(ServerSocket);
closesocket(ClientSocket);
WSACleanup();
return 0;
}
多線程就是把用戶端的代碼複制,再建立一個項目,然後把是以的用戶端和伺服器都運作起來就好了,怎麼一次性運作多個項目在我另外的文章有)
用戶端:
// client.cpp : 此檔案包含 "main" 函數。程式執行将在此處開始并結束。
//
#include "pch.h"
#include <iostream>
#include <winsock2.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
#define PORT 4000
#define IP_ADDRESS "127.0.0.1"
int main(int argc, char * argv[])
{
WSADATA Ws;
SOCKET ClientSocket;
struct sockaddr_in ServerAddr;
int Ret = 0;
int AddrLen = 0;
HANDLE hThread = NULL;
char SendBuffer[MAX_PATH];
//Init Windows Socket
if (WSAStartup(MAKEWORD(2, 2), &Ws) != 0)
{
cout << "Init Windows Socket Failed::" << GetLastError() << endl;
return -1;
}
//Create Socket
ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ClientSocket == INVALID_SOCKET)
{
cout << "Create Socket Failed::" << GetLastError() << endl;
return -1;
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
ServerAddr.sin_port = htons(PORT);
memset(ServerAddr.sin_zero, 0x00, 8);
Ret = connect(ClientSocket, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
if (Ret == SOCKET_ERROR)
{
cout << "Connect Error::" << GetLastError() << endl;
return -1;
}
else
{
cout << "連接配接成功!" << endl;
}
char RecvBuffer[MAX_PATH];//接收到的資訊
while (true)
{
cin.getline(SendBuffer, sizeof(SendBuffer));
Ret = send(ClientSocket, SendBuffer, (int)strlen(SendBuffer), 0);
if (Ret == SOCKET_ERROR)
{
cout << "Send Info Error::" << GetLastError() << endl;
break;
}
memset(RecvBuffer, 0x00, sizeof(RecvBuffer));//初始化
Ret = recv(ClientSocket, RecvBuffer, MAX_PATH, 0);//接收伺服器傳回的資訊
cout << "接收到伺服器資訊為:" << RecvBuffer << endl;//輸出接收到的資訊
}
closesocket(ClientSocket);
WSACleanup();
return 0;
}
// 運作程式: Ctrl + F5 或調試 >“開始執行(不調試)”菜單
// 調試程式: F5 或調試 >“開始調試”菜單
// 入門提示:
// 1. 使用解決方案資料總管視窗添加/管理檔案
// 2. 使用團隊資料總管視窗連接配接到源代碼管理
// 3. 使用輸出視窗檢視生成輸出和其他消息
// 4. 使用錯誤清單視窗檢視錯誤
// 5. 轉到“項目”>“添加新項”以建立新的代碼檔案,或轉到“項目”>“添加現有項”以将現有代碼檔案添加到項目
// 6. 将來,若要再次打開此項目,請轉到“檔案”>“打開”>“項目”并選擇 .sln 檔案