流式套接字编程多线程通信
环境:VS2017
首先,附上原作者的文章链接:
作者:弱菜zc
来源:CSDN
原文:https ://blog.csdn.net/zchahaha/article/details/56831242
版权声明:本文为博主原创文章,转载请附上博文链接!
新建一个控制台应用程序 ,新建一个解决方案,当然,新建应用程序的时候已经帮你新建好了解决方案,新建两个项目,一个放服务器,一个放客户端。


代码区:(注意:服务器和客户端的IP都是使用回环地址,如果只是在本地运行,改为自己本机的IP就行了)
服务器:
#include"pch.h"
#include
#include
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
#include
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 文件