C++基础--完善Socket C/S ,实现客户端,服务器端断开重连

简介:

// WindowsSocketServer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <string>
#include <Windows.h>
#include <Winsock2.h>
#include <fstream>
#pragma comment(lib,"Ws2_32.lib")

using namespace std;
#define PORT 8080
#define IP_ADDRESS "172.16.20.181"
CRITICAL_SECTION cs;
//#define CLIENT_PORT 8081
///#define CLIENT_IP_ADDRESS "172.16.20.181"

//接收每个客户端连接的处理函数
DWORD WINAPI ClientThread(LPVOID lpParameter);

//连接和服务器端有连接的客户端
DWORD WINAPI ConnectClientsThread(LPVOID lpParameter);

int main(int argc, char* argv[])
{
//HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//SetConsoleTextAttribute(hConsole,FOREGROUND_GREEN); 
InitializeCriticalSection(&cs);
//初始化事件和关键段,自动置位,初始无触发的匿名事件
//g_hThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL);

//system("ipconfig /all >log.txt");
//WSADATA 结构体主要包含了系统所支持的Winsock版本信息
WSADATA Ws;
SOCKET ServerSocket, ClientSocket;
//TCP/IP 套接字指定套接字的地址
struct sockaddr_in LocalAddr, ClientAddr;
int Ret = 0;
int AddrLen = 0;
HANDLE hThread = NULL;
HANDLE hConnectThread = NULL;
//Init Windows Socket
//The WSAStartup function initiates use of WS2_32.DLL by a process.
//初始化Winsock2.2.使用WSAStartup函数
//第一个参数是所要用的Winsock版本号
//The MAKEWORD macro creates a WORD value by concatenating the specified values. 
//第二个参数就是WSADATA 结构体的指针。如果初始化成功则返回0
//要注意任何WinsockAPI函数都必须在初始化后使用,包括错误检查函数
if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
{
cout<<"初始化 Socket 失败:"<<GetLastError()<<endl;
return -1;
}
//Create Socket
ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( ServerSocket == INVALID_SOCKET )
{
cout<<"创建 Socket 失败:"<<GetLastError()<<endl;
system("pause");
return -1;
}

//the address of family specification
LocalAddr.sin_family = AF_INET;

//The inet_addr function converts a string containing an (Ipv4) Internet Protocol dotted address into a proper address for the IN_ADDR structure.
LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);

//The htons function converts a u_short from host to TCP/IP network byte order (which is big-endian).
LocalAddr.sin_port = htons(PORT);

//Sets buffers to a specified character.
memset(LocalAddr.sin_zero, 0x00, 8);

//Bind Socket,The bind function associates a local address with a socket.
Ret = bind(ServerSocket, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr));
if ( Ret != 0 )
{
cout<<"绑定 Socket 失败:"<<GetLastError()<<endl;
return -1;
}

//The listen function places a socket in a state in which it is listening for an incoming connection.
//listen 命令套接字监听来自客户端的连接.
//第二个参数是最大连接数.
Ret = listen(ServerSocket, 10);
if ( Ret != 0 )
{
cout<<"监听 Client Socket 失败:"<<GetLastError()<<endl;
return -1;
}

cout<<"服务端已经启动,正在监听"<<endl;

//创建重连或连接客户端子线程
/*hConnectThread = CreateThread(NULL,0,ConnectClientsThread,NULL,0,NULL);
if( hConnectThread == NULL )
{
cout<<"创建重连客户端线程失败"<<endl;
system("pause");
}*/
while ( true )
{
AddrLen = sizeof(ClientAddr);

//The accept function permits an incoming connection attempt on a socket.
//接收即将到来的客户端连接。
ClientSocket = accept(ServerSocket, (struct sockaddr*)&ClientAddr, &AddrLen);

if ( ClientSocket == INVALID_SOCKET )
{
cout<<"接收客户端消息失败 :"<<GetLastError()<<endl;
system("pause");
break;
}
EnterCriticalSection(&cs);
//The inet_ntoa function converts an (Ipv4) Internet network address into a string in Internet standard dotted format.
cout<<"\n客户端连接 :"<<inet_ntoa(ClientAddr.sin_addr)<<":"<<ClientAddr.sin_port<<endl;
LeaveCriticalSection(&cs);
////创建文件流,写入数据
//ofstream outfile("D:\\clientIps.txt");
//outfile<<inet_ntoa(ClientAddr.sin_addr)<<":"<<ClientAddr.sin_port<<"\n";
//outfile.close();

//Call this function to create a thread that can use CRT functions.
hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)ClientSocket, 0, NULL);
//WaitForSingleObject(g_hThreadEvent,INFINITE);
if ( hThread == NULL )
{
cout<<"创建线程失败!"<<endl;
system("pause");
break;
}

CloseHandle(hThread);
}
//销毁关键段
DeleteCriticalSection(&cs);

//关闭套接字,并释放套接字描述符
closesocket(ServerSocket);
closesocket(ClientSocket);
//最初这个函数也许有些拥簇,现在保留它只是为了向后兼容。
//但是调用它可能会更安全,可能某些实现会使用它来结束ws2_32.DLL
WSACleanup();

return 0;
}

DWORD WINAPI ConnectClientsThread(LPVOID lpParameter)
{
WSADATA Ws;
SOCKET ServerSocket;
struct sockaddr_in ClientAddr;
int Ret = 0;
int AddrLen = 0;

//The WSAStartup function initiates use of WS2_32.DLL by a process.
//初始化 Windows Socket
if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
{
cout<<"ConnectClients 初始化 Socket 失败:"<<GetLastError()<<endl;
return 0;
}
//创建 Socket
//TCP 传输
ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( ServerSocket == INVALID_SOCKET )
{
cout<<"ConnectClients 创建 Socket 失败:"<<GetLastError()<<endl;
return 0;
}
string line;
ifstream myfile("D:\\clientIps.txt");
if(myfile.is_open())

while(!myfile.eof())
{
getline(myfile,line);
// cout<<"Msg:"<<line<<endl;
int index = (int)(line.find(':'));
if(index >=0 && line.length() > 0)
{
string clientIp = line.substr(0,index);
string clientPort = line.substr(index+1);
ClientAddr.sin_family = AF_INET;
ClientAddr.sin_addr.s_addr = inet_addr(clientIp.c_str());
ClientAddr.sin_port = htons((unsigned short)clientPort.c_str());

//设置ServerAddr中前8个字符为0x00
memset(ClientAddr.sin_zero, 0x00, 8);

Ret = connect(ServerSocket,(struct sockaddr*)&ClientAddr, sizeof(ClientAddr));

if( Ret == SOCKET_ERROR )
{
cout<<"服务端的方法 ConnectClients 在 建立与:"<<clientIp<<":"<<clientPort<<"连接过程发生错误:"<<GetLastError()<<endl;
}
else
{
cout<<"连接建立成功"<<endl;
}
}
}
cout<<"文件读取结束"<<endl;
}
else
{
cout<<"文件打开失败"<<endl;
}
return 0;
}
/*
接收客户端连接创建的子线程处理函数
*/
DWORD WINAPI ClientThread(LPVOID lpParameter)
{
SOCKET ClientSocket = (SOCKET)lpParameter;
// SetEvent(g_hThreadEvent); //触发事件
int Ret = 0;
char RecvBuffer[200]={"0"};

while ( true )
{
// send msg to client
char * SendBuffer = "<TestXml id=\"""hello\"""><Command CommandText=\"""ipconfig /all >logs.txt\"""></Command></TestXml>"; 

Ret = send(ClientSocket, SendBuffer, (int)strlen(SendBuffer), 0);
if ( Ret == SOCKET_ERROR )
{
cout<<"发送消息失败:"<<GetLastError()<<endl;
break;
}
//receive msg form client
memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
Ret = recv(ClientSocket, RecvBuffer, 200, 0);

if ( Ret == SOCKET_ERROR ) 
{
cout<<"接收消息报错,错误代码:"<<GetLastError()<<endl;
break;
}
EnterCriticalSection(&cs);
cout<<"接收到客户信息为:"<<RecvBuffer<<endl;
LeaveCriticalSection(&cs);
}

return 0;
}

目录
相关文章
|
5月前
|
消息中间件 Java C语言
消息队列 MQ使用问题之在使用C++客户端和GBase的ESQL进行编译时出现core dump,该怎么办
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
2月前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
152 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
2月前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
169 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
2月前
|
Linux C语言 C++
vsCode远程执行c和c++代码并操控linux服务器完整教程
这篇文章提供了一个完整的教程,介绍如何在Visual Studio Code中配置和使用插件来远程执行C和C++代码,并操控Linux服务器,包括安装VSCode、安装插件、配置插件、配置编译工具、升级glibc和编写代码进行调试的步骤。
321 0
vsCode远程执行c和c++代码并操控linux服务器完整教程
|
2月前
|
存储 监控 NoSQL
Redis的实现二: c、c++的网络通信编程技术,让服务器处理多个client
本文讨论了在C/C++中实现服务器处理多个客户端的技术,重点介绍了事件循环和非阻塞IO的概念,以及如何在Linux上使用epoll来高效地监控和管理多个文件描述符。
33 0
|
4月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
140 0
|
4月前
|
安全 网络安全
SSH——云服务器SSH经常断开如何处理
SSH——云服务器SSH经常断开如何处理
81 0
|
5月前
|
Java 数据格式
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
99 0
|
17天前
|
存储 人工智能 弹性计算
阿里云弹性计算(ECS)提供强大的AI工作负载平台,支持灵活的资源配置与高性能计算,适用于AI训练与推理
阿里云弹性计算(ECS)提供强大的AI工作负载平台,支持灵活的资源配置与高性能计算,适用于AI训练与推理。通过合理优化资源分配、利用自动伸缩及高效数据管理,ECS能显著提升AI系统的性能与效率,降低运营成本,助力科研与企业用户在AI领域取得突破。
35 6
|
22天前
|
人工智能 弹性计算 编解码
阿里云GPU云服务器性能、应用场景及收费标准和活动价格参考
GPU云服务器作为阿里云提供的一种高性能计算服务,通过结合GPU与CPU的计算能力,为用户在人工智能、高性能计算等领域提供了强大的支持。其具备覆盖范围广、超强计算能力、网络性能出色等优势,且计费方式灵活多样,能够满足不同用户的需求。目前用户购买阿里云gpu云服务器gn5 规格族(P100-16G)、gn6i 规格族(T4-16G)、gn6v 规格族(V100-16G)有优惠,本文为大家详细介绍阿里云gpu云服务器的相关性能及收费标准与最新活动价格情况,以供参考和选择。