天天看點

網絡程式設計:TCP流式套接字多線程通信流式套接字程式設計多線程通信

流式套接字程式設計多線程通信

環境: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 檔案
           

繼續閱讀