// 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;
}

C++基础--完善Socket C/S ,实现客户端,服务器端断开重连的更多相关文章

  1. 基于socket、多线程的客户端服务器端聊天程序

    服务器端: using System; using System.Windows.Forms; using System.Net.Sockets; using System.Net;//IPAddre ...

  2. 你得学会并且学得会的Socket编程基础知识(续)——Silverlight客户端

    本文将在这个案例的基础上,加入一个特殊场景,利用Silverlight来实现客户端.有的朋友可能会说,其实是一样的吧.请不要急于下结论,有用过Silverlight的朋友都有这种体会,很多在标准.NE ...

  3. 网络编程基础【day09】:通过socket实现简单ssh客户端(三)

    本节内容 1.概述 2.socket发送中文 3.重复发送和多次接收 4.模拟ssh客户端 一.概述 本篇博客讲一下,如果socket客户端断了,另外的客户端怎么接入服务端,还有模拟ssh的链接等. ...

  4. 在Livemedia的基础上开发自己的流媒体客户端 V 0.01

    在Livemedia的基础上开发自己的流媒体客户端 V 0.01 桂堂东 xiaoguizi@gmail.com 2004-10 2004-12 友情申明: 本文档适合已经从事流媒体传输工作或者对网络 ...

  5. Python 基础之socket编程(一)

    Python 基础之socket编程(一) 可以进行通信玩儿了,感觉不错不错,网络通信就像打电话,我说一句你听一句之后,你再说一句,我听一句,就这样.....下去了.不扯淡了,来来来,看看今天都搞了点 ...

  6. 使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)

    原文:使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置) 在上一篇中说到了Silverlight下的Socket通信,在最后的时候说到本篇将会结合地图. ...

  7. Python 基础之socket编程(二)

    Python 基础之socket编程(二) 昨天只是对socket编程做了简单的介绍,只是把socket通信的框架搭建起来,要对其中的功能进行进一步的扩充,就来看看今天的料哈! 一.基于tcp的套接字 ...

  8. python基础之socket与socketserver

    ---引入 Socket的英文原义是“孔”或“插座”,在Unix的进程通信机制中又称为‘套接字’.套接字实际上并不复杂,它是由一个ip地址以及一个端口号组成.Socket正如其英文原意那样,像一个多孔 ...

  9. python基础之socket编程 (转自林海峰老师)

    python基础之socket编程   阅读目录 一 客户端/服务器架构 二 osi七层 三 socket层 四 socket是什么 五 套接字发展史及分类 六 套接字工作流程 七 基于TCP的套接字 ...

随机推荐

  1. SocketIO总结

    我在马克飞象上写的一样的内容,感觉那个样式好看的:WorkerMan的部分总结 workerman中部分函数总结 以下是把我搜集到的资料进行了一个整合.详细怎么使用.慢慢摸索吧. Worker类 中文 ...

  2. ZooKeeper 授权验证

    ZooKeeper 授权验证 学习了:https://blog.csdn.net/liuyuehu/article/details/52121755 zookeeper可以进行认证授权:

  3. 使用 sftp 向linux服务器传输文件

    sftp是加密的文件传输. 登陆 sftp name@123.21.331.1 1 2.把本地文件name1传到服务器name2下 put /name1.html /name2/ 1 把服务器name ...

  4. Codeforces Round #313 (Div. 2) ABC

    A http://codeforces.com/contest/560/problem/A 推断给出的数能否组成全部自然数. 水题 int a[1010]; bool b[1000010]; int ...

  5. C#复习总结6 (需要进一步复习)

    第十七章 泛型 什么是泛型 泛型是为了适应多种不同种类的数据类型而存在的.有了它之后,我们可以不用为不同的数据类型而单独写一个适配.这样很麻烦. 类型不是对象,而是对象的模板.泛型类型也不是类型,而是 ...

  6. gulp-gulpfile.js语法说明

    关于gulpfile文件: 直接上代码吧!! /*! * gulp * $ npm install gulp gulp-ruby-sass gulp-cached gulp-uglify gulp-r ...

  7. PHP ORM操作MySQL数据库

    ORM----Oriented Relationship Mapper,即用面向对象的方式来操作数据库.归根结底,还是对于SQL语句的封装. 首先,我们的数据库有如下一张表: 我们希望能够对这张表,利 ...

  8. tomcat 7安装

    JAVA环境安装 1.下载包 http://download.oracle.com/otn/java/jdk/6u45-b06/jdk-6u45-linux-x64.bin 2.安装 jdk-6u45 ...

  9. iOS用户是否打开APP通知开关跳转到系统的设置界面

    1.检测用户是否打开推送通知  /** 系统通知是否打开 @return 是否打开 */ //检测通知是否打开iOS8以后有所变化 所以需要适配iOS7 + (BOOL)openThePushNoti ...

  10. java 多线程2(转载)

    http://www.cnblogs.com/DreamSea/archive/2012/01/11/JavaThread.html Ø线程的概述(Introduction) 线程是一个程序的多个执行 ...