1 // WindowsSocketServer.cpp : 定义控制台应用程序的入口点。
2 //
3
4 #include "stdafx.h"
5 #include <iostream>
6 #include <string>
7 #include <Windows.h>
8 #include <Winsock2.h>
9 #include <fstream>
10 #pragma comment(lib,"Ws2_32.lib")
11
12 using namespace std;
13 #define PORT 8080
14 #define IP_ADDRESS "172.16.20.181"
15 CRITICAL_SECTION cs;
16 //#define CLIENT_PORT 8081
17 ///#define CLIENT_IP_ADDRESS "172.16.20.181"
18
19 //接收每个客户端连接的处理函数
20 DWORD WINAPI ClientThread(LPVOID lpParameter);
21
22 //连接和服务器端有连接的客户端
23 DWORD WINAPI ConnectClientsThread(LPVOID lpParameter);
24
25 int main(int argc, char* argv[])
26 {
27 //HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
28 //SetConsoleTextAttribute(hConsole,FOREGROUND_GREEN);
29 InitializeCriticalSection(&cs);
30 //初始化事件和关键段,自动置位,初始无触发的匿名事件
31 //g_hThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
32
33 //system("ipconfig /all >log.txt");
34 //WSADATA 结构体主要包含了系统所支持的Winsock版本信息
35 WSADATA Ws;
36 SOCKET ServerSocket, ClientSocket;
37 //TCP/IP 套接字指定套接字的地址
38 struct sockaddr_in LocalAddr, ClientAddr;
39 int Ret = 0;
40 int AddrLen = 0;
41 HANDLE hThread = NULL;
42 HANDLE hConnectThread = NULL;
43 //Init Windows Socket
44 //The WSAStartup function initiates use of WS2_32.DLL by a process.
45 //初始化Winsock2.2.使用WSAStartup函数
46 //第一个参数是所要用的Winsock版本号
47 //The MAKEWORD macro creates a WORD value by concatenating the specified values.
48 //第二个参数就是WSADATA 结构体的指针。如果初始化成功则返回0
49 //要注意任何WinsockAPI函数都必须在初始化后使用,包括错误检查函数
50 if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
51 {
52 cout<<"初始化 Socket 失败:"<<GetLastError()<<endl;
53 return -1;
54 }
55 //Create Socket
56 ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
57 if ( ServerSocket == INVALID_SOCKET )
58 {
59 cout<<"创建 Socket 失败:"<<GetLastError()<<endl;
60 system("pause");
61 return -1;
62 }
63
64 //the address of family specification
65 LocalAddr.sin_family = AF_INET;
66
67 //The inet_addr function converts a string containing an (Ipv4) Internet Protocol dotted address into a proper address for the IN_ADDR structure.
68 LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
69
70 //The htons function converts a u_short from host to TCP/IP network byte order (which is big-endian).
71 LocalAddr.sin_port = htons(PORT);
72
73 //Sets buffers to a specified character.
74 memset(LocalAddr.sin_zero, 0x00, 8);
75
76 //Bind Socket,The bind function associates a local address with a socket.
77 Ret = bind(ServerSocket, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr));
78 if ( Ret != 0 )
79 {
80 cout<<"绑定 Socket 失败:"<<GetLastError()<<endl;
81 return -1;
82 }
83
84 //The listen function places a socket in a state in which it is listening for an incoming connection.
85 //listen 命令套接字监听来自客户端的连接.
86 //第二个参数是最大连接数.
87 Ret = listen(ServerSocket, 10);
88 if ( Ret != 0 )
89 {
90 cout<<"监听 Client Socket 失败:"<<GetLastError()<<endl;
91 return -1;
92 }
93
94 cout<<"服务端已经启动,正在监听"<<endl;
95
96 //创建重连或连接客户端子线程
97 /*hConnectThread = CreateThread(NULL,0,ConnectClientsThread,NULL,0,NULL);
98 if( hConnectThread == NULL )
99 {
100 cout<<"创建重连客户端线程失败"<<endl;
101 system("pause");
102 }*/
103 while ( true )
104 {
105 AddrLen = sizeof(ClientAddr);
106
107 //The accept function permits an incoming connection attempt on a socket.
108 //接收即将到来的客户端连接。
109 ClientSocket = accept(ServerSocket, (struct sockaddr*)&ClientAddr, &AddrLen);
110
111 if ( ClientSocket == INVALID_SOCKET )
112 {
113 cout<<"接收客户端消息失败 :"<<GetLastError()<<endl;
114 system("pause");
115 break;
116 }
117 EnterCriticalSection(&cs);
118 //The inet_ntoa function converts an (Ipv4) Internet network address into a string in Internet standard dotted format.
119 cout<<"\n客户端连接 :"<<inet_ntoa(ClientAddr.sin_addr)<<":"<<ClientAddr.sin_port<<endl;
120 LeaveCriticalSection(&cs);
121 ////创建文件流,写入数据
122 //ofstream outfile("D:\\clientIps.txt");
123 //outfile<<inet_ntoa(ClientAddr.sin_addr)<<":"<<ClientAddr.sin_port<<"\n";
124 //outfile.close();
125
126 //Call this function to create a thread that can use CRT functions.
127 hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)ClientSocket, 0, NULL);
128 //WaitForSingleObject(g_hThreadEvent,INFINITE);
129 if ( hThread == NULL )
130 {
131 cout<<"创建线程失败!"<<endl;
132 system("pause");
133 break;
134 }
135
136 CloseHandle(hThread);
137 }
138 //销毁关键段
139 DeleteCriticalSection(&cs);
140
141 //关闭套接字,并释放套接字描述符
142 closesocket(ServerSocket);
143 closesocket(ClientSocket);
144 //最初这个函数也许有些拥簇,现在保留它只是为了向后兼容。
145 //但是调用它可能会更安全,可能某些实现会使用它来结束ws2_32.DLL
146 WSACleanup();
147
148 return 0;
149 }
150
151 DWORD WINAPI ConnectClientsThread(LPVOID lpParameter)
152 {
153 WSADATA Ws;
154 SOCKET ServerSocket;
155 struct sockaddr_in ClientAddr;
156 int Ret = 0;
157 int AddrLen = 0;
158
159 //The WSAStartup function initiates use of WS2_32.DLL by a process.
160 //初始化 Windows Socket
161 if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
162 {
163 cout<<"ConnectClients 初始化 Socket 失败:"<<GetLastError()<<endl;
164 return 0;
165 }
166 //创建 Socket
167 //TCP 传输
168 ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
169 if ( ServerSocket == INVALID_SOCKET )
170 {
171 cout<<"ConnectClients 创建 Socket 失败:"<<GetLastError()<<endl;
172 return 0;
173 }
174 string line;
175 ifstream myfile("D:\\clientIps.txt");
176 if(myfile.is_open())
177 {
178 while(!myfile.eof())
179 {
180 getline(myfile,line);
181 // cout<<"Msg:"<<line<<endl;
182 int index = (int)(line.find(':'));
183 if(index >=0 && line.length() > 0)
184 {
185 string clientIp = line.substr(0,index);
186 string clientPort = line.substr(index+1);
187 ClientAddr.sin_family = AF_INET;
188 ClientAddr.sin_addr.s_addr = inet_addr(clientIp.c_str());
189 ClientAddr.sin_port = htons((unsigned short)clientPort.c_str());
190
191 //设置ServerAddr中前8个字符为0x00
192 memset(ClientAddr.sin_zero, 0x00, 8);
193
194 Ret = connect(ServerSocket,(struct sockaddr*)&ClientAddr, sizeof(ClientAddr));
195
196 if( Ret == SOCKET_ERROR )
197 {
198 cout<<"服务端的方法 ConnectClients 在 建立与:"<<clientIp<<":"<<clientPort<<"连接过程发生错误:"<<GetLastError()<<endl;
199 }
200 else
201 {
202 cout<<"连接建立成功"<<endl;
203 }
204 }
205 }
206 cout<<"文件读取结束"<<endl;
207 }
208 else
209 {
210 cout<<"文件打开失败"<<endl;
211 }
212 return 0;
213 }
214 /*
215 接收客户端连接创建的子线程处理函数
216 */
217 DWORD WINAPI ClientThread(LPVOID lpParameter)
218 {
219 SOCKET ClientSocket = (SOCKET)lpParameter;
220 // SetEvent(g_hThreadEvent); //触发事件
221 int Ret = 0;
222 char RecvBuffer[200]={"0"};
223
224 while ( true )
225 {
226 // send msg to client
227 char * SendBuffer = "<TestXml id=\"""hello\"""><Command CommandText=\"""ipconfig /all >logs.txt\"""></Command></TestXml>";
228
229 Ret = send(ClientSocket, SendBuffer, (int)strlen(SendBuffer), 0);
230 if ( Ret == SOCKET_ERROR )
231 {
232 cout<<"发送消息失败:"<<GetLastError()<<endl;
233 break;
234 }
235 //receive msg form client
236 memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
237 Ret = recv(ClientSocket, RecvBuffer, 200, 0);
238
239 if ( Ret == SOCKET_ERROR )
240 {
241 cout<<"接收消息报错,错误代码:"<<GetLastError()<<endl;
242 break;
243 }
244 EnterCriticalSection(&cs);
245 cout<<"接收到客户信息为:"<<RecvBuffer<<endl;
246 LeaveCriticalSection(&cs);
247 }
248
249 return 0;
250 }
1 // WindowsSocketClient.cpp : 定义控制台应用程序的入口点。
2 //
3
4 #include "stdafx.h"
5 #include <iostream>
6 #include <Winsock2.h>
7 #include <Windows.h>
8 #include <fstream>
9 #include <map>
10 #include <string>
11 #include <sstream>
12 #include "tinystr.h"
13 #include "tinyxml.h"
14 #pragma comment(lib,"Ws2_32.lib")
15
16 using namespace std;
17
18 #define PORT 8080
19 #define IP_ADDRESS "172.16.20.181"
20
21 #define LISTEN_PORT 8081
22 #define LISTEN_IP_ADDRESS "172.16.20.181"
23 //发送消息结构体
24 struct SendMsgStruct
25 {
26 SOCKET clientSocket;
27 string msg;
28 struct sockaddr_in ServerAddr;
29 };
30
31 //接收消息结构体
32 struct RecvMsgStruct
33 {
34 SOCKET clientSocket;
35 struct sockaddr_in ServerAddr;
36 };
37
38 //发送消息子线程
39 DWORD WINAPI SendThread(LPVOID lpParameter);
40
41 //接收消息子线程
42 DWORD WINAPI RecvThread(LPVOID lpParameter);
43
44 //去除字符串首尾空格
45 void trim(string &str);
46
47 //监听服务器的连接
48 DWORD WINAPI ListenServerThread(LPVOID lpParameter);
49
50 int _tmain(int argc, _TCHAR* argv[])
51 {
52 //HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
53 //SetConsoleTextAttribute(hConsole,FOREGROUND_GREEN);
54
55 WSADATA Ws;
56 SOCKET ClientSocket,ServerSocket;
57 struct sockaddr_in ServerAddr;
58 int Ret = 0;
59 int AddrLen = 0;
60 HANDLE hThread = NULL;
61 HANDLE hSendThread = NULL;
62 HANDLE hRevcThread = NULL;
63 HANDLE hListenThread = NULL;
64 //The WSAStartup function initiates use of WS2_32.DLL by a process.
65 //初始化 Windows Socket
66 if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
67 {
68 cout<<"初始化 Socket 失败:"<<GetLastError()<<endl;
69 return -1;
70 }
71
72 //创建 Socket
73 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
74 if ( ClientSocket == INVALID_SOCKET )
75 {
76 cout<<"创建 Socket 失败:"<<GetLastError()<<endl;
77 return -1;
78 }
79
80 ServerAddr.sin_family = AF_INET;
81 ServerAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
82 ServerAddr.sin_port = htons(PORT);
83
84 //设置ServerAddr中前8个字符为0x00
85 memset(ServerAddr.sin_zero, 0x00, 8);
86
87 Ret = connect(ClientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
88
89 if( Ret == SOCKET_ERROR )
90 {
91 cout<<"建立连接过程发生错误:"<<GetLastError()<<endl;
92 }
93 else
94 {
95 cout<<"连接建立成功"<<endl;
96 }
97 //创建一个子线程,监听从服务器过来的连接
98 /*hListenThread = CreateThread(NULL, 0, ListenServerThread, NULL, 0, NULL);
99 WaitForSingleObject(hListenThread,INFINITE);
100 if( hListenThread == NULL )
101 {
102 cout<<"创建监听服务器对客户端的连接子线程失败"<<endl;
103 system("pause");
104 return -1;
105 }*/
106 //创建一个子线程,用于向服务器端发送消息
107 struct SendMsgStruct *msgSend = new struct SendMsgStruct();
108 msgSend->clientSocket = ClientSocket;
109 msgSend->msg = "你好,Msg From Client";
110 msgSend->ServerAddr = ServerAddr;
111 //传递一个struct
112 hSendThread = CreateThread(NULL, 0, SendThread, (LPVOID)msgSend, 0, NULL);
113 WaitForSingleObject(hSendThread, INFINITE);
114
115 if( hSendThread == NULL )
116 {
117 cout<<"创建发送消息子线程失败"<<endl;
118 system("pause");
119 return -1;
120 }
121
122 //创建一个子线程,用于接收从服务器端发送过来的消息
123 struct RecvMsgStruct *msgRecv = new struct RecvMsgStruct();
124 msgRecv->clientSocket = ClientSocket;
125 msgRecv->ServerAddr = ServerAddr;
126 //传递一个struct指针参数
127 hRevcThread = CreateThread(NULL,0,RecvThread,(LPVOID)msgRecv,0,NULL);
128 WaitForSingleObject(hRevcThread, INFINITE);
129
130 if( hRevcThread == NULL )
131 {
132 cout<<"创建接收消息子线程失败"<<endl;
133 system("pause");
134 return -1;
135 }
136
137 //客户端输入exit,退出
138 string clientString ;
139 do
140 {
141 getline(cin,clientString);
142
143 }while( clientString != "exit" && clientString !="EXIT");
144 closesocket(ClientSocket);
145 WSACleanup();
146 system("pause");
147 return 0;
148 }
149
150 //监听服务器连接子线程
151 DWORD WINAPI ListenServerThread(LPVOID lpParameter)
152 {
153 //HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
154 //SetConsoleTextAttribute(hConsole,FOREGROUND_GREEN);
155
156 //system("ipconfig /all >log.txt");
157 //WSADATA 结构体主要包含了系统所支持的Winsock版本信息
158 WSADATA Ws;
159 SOCKET ServerSocket, ClientSocket;
160 //TCP/IP 套接字指定套接字的地址
161 struct sockaddr_in LocalAddr, ServerAddr;
162 int Ret = 0;
163 int AddrLen = 0;
164 HANDLE hThread = NULL;
165
166 //初始化Winsock2.2.使用WSAStartup函数
167 //第一个参数是所要用的Winsock版本号
168 //The MAKEWORD macro creates a WORD value by concatenating the specified values.
169 //第二个参数就是WSADATA 结构体的指针。如果初始化成功则返回0
170 //要注意任何WinsockAPI函数都必须在初始化后使用,包括错误检查函数
171 if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
172 {
173 cout<<"初始化 Socket 失败:"<<GetLastError()<<endl;
174 return 0;
175 }
176 //Create Socket
177 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
178 if ( ClientSocket == INVALID_SOCKET )
179 {
180 cout<<"创建客户端 Socket 失败:"<<GetLastError()<<endl;
181 system("pause");
182 return 0;
183 }
184
185 //the address of family specification
186 LocalAddr.sin_family = AF_INET;
187
188 //The inet_addr function converts a string containing an (Ipv4) Internet Protocol dotted address into a proper address for the IN_ADDR structure.
189 LocalAddr.sin_addr.s_addr = inet_addr(LISTEN_IP_ADDRESS);
190
191 //The htons function converts a u_short from host to TCP/IP network byte order (which is big-endian).
192 LocalAddr.sin_port = htons(LISTEN_PORT);
193
194 //Sets buffers to a specified character.
195 memset(LocalAddr.sin_zero, 0x00, 8);
196
197 //Bind Socket,The bind function associates a local address with a socket.
198 Ret = bind(ClientSocket, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr));
199 if ( Ret != 0 )
200 {
201 cout<<"绑定 Socket 失败:"<<GetLastError()<<endl;
202 return 0;
203 }
204
205 //listen 命令套接字监听来自服务端的连接.
206 //第二个参数是最大连接数.
207 Ret = listen(ClientSocket, 10);
208 if ( Ret != 0 )
209 {
210 cout<<"监听 Server Socket 失败:"<<GetLastError()<<endl;
211 return 0;
212 }
213
214 cout<<"客户端已经启动,正在监听"<<endl;
215
216 AddrLen = sizeof(ServerAddr);
217
218 //The accept function permits an incoming connection attempt on a socket.
219 //接收即将到来的客户端连接。
220 ServerSocket = accept(ClientSocket, (struct sockaddr*)&ServerAddr, &AddrLen);
221
222 if ( ClientSocket == INVALID_SOCKET )
223 {
224 cout<<"接收服务器端消息失败 :"<<GetLastError()<<endl;
225 system("pause");
226 // break;
227 }
228 else
229 {
230 //The inet_ntoa function converts an (Ipv4) Internet network address into a string in Internet standard dotted format.
231 cout<<"\n服务器端连接 :"<<inet_ntoa(ServerAddr.sin_addr)<<":"<<ServerAddr.sin_port<<endl;
232 }
233 string cmdstr ;
234 do
235 {
236 getline(cin,cmdstr);
237 }while(cmdstr != "exit" && cmdstr != "EXIT");
238 closesocket(ClientSocket);
239 //最初这个函数也许有些拥簇,现在保留它只是为了向后兼容。
240 //但是调用它可能会更安全,可能某些实现会使用它来结束ws2_32.DLL
241 WSACleanup();
242
243 return 0;
244 }
245
246 //发送消息子线程
247 DWORD WINAPI SendThread(LPVOID lpParameter)
248 {
249 SendMsgStruct *myStruct = (SendMsgStruct *)lpParameter;
250 SOCKET ClientSocket = myStruct->clientSocket;
251 string SendMsg = myStruct->msg;
252 struct sockaddr_in ServerAddr = myStruct->ServerAddr;
253
254 while( true )
255 {
256 int flag = 0;
257 int bufSize = SendMsg.length();
258 char * buf = const_cast<char*>(SendMsg.c_str());
259 flag = send(ClientSocket, buf, bufSize, 0);
260
261 //判断当前时候存在可用连接,如果没有,再次连接
262 while( flag == -1 || flag == 0)
263 {
264 cout<<"准备重连"<<endl;
265 //shutdown(ClientSocket,2);
266 closesocket(ClientSocket);
267 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
268 int cunnectFlag = connect(ClientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
269
270 if( cunnectFlag == SOCKET_ERROR )
271 {
272 cout<<"重连失败 :"<<GetLastError()<<endl;
273 Sleep(5000);
274 //cunnectFlag = connect(ClientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
275 }
276 else
277 {
278 break;
279 }
280 }
281
282 //传输过程中报错
283 //if( flag == SOCKET_ERROR )
284 //{
285 // cout<<"消息发送过程中报错:"<<GetLastError()<<endl;
286 //}
287 //没有传输完成
288 //else if( flag < bufSize )
289 if( flag < bufSize )
290 {
291 flag = send(ClientSocket, buf, bufSize - flag, 0);
292 }
293 //传输成功
294 else
295 {
296 cout<<"\n消息传输成功"<<endl;
297 }
298
299 //每5秒发送一次
300 Sleep(5000);
301 }
302 return 0;
303 }
304
305 //接收消息子线程
306 DWORD WINAPI RecvThread(LPVOID lpParameter)
307 {
308
309 RecvMsgStruct *recvStruct=(RecvMsgStruct *)lpParameter;
310 SOCKET clientSocket = recvStruct->clientSocket;
311 struct sockaddr_in ServerAddr = recvStruct->ServerAddr;
312 char recvBuf[500]={"0"};
313 int byteRecv = recv(clientSocket, recvBuf, 500, 0);
314 int connectState;
315 while( byteRecv == 0 )
316 {
317 //连接断开,重连
318 cout<<"byteRecv == 0"<<endl;
319 shutdown(clientSocket,2);
320 //closesocket(ClientSocket);
321 clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
322 connectState = connect(clientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
323
324 if( connectState == SOCKET_ERROR )
325 {
326 cout<<"建立连接发生错误,错误代码:"<<GetLastError()<<endl;
327 }
328 else
329 {
330 cout<<"-----------------------------------------------In"<<endl;
331 byteRecv = recv(clientSocket, recvBuf, 500, 0);//建立连接后,重新获取一次消息
332 recvBuf[byteRecv]=0;
333 }
334 Sleep(5000);
335 }
336 cout<<recvBuf<<endl;
337 return 0;
338 }
339
340 //移除字符串首尾空格
341 void trim(string &str)
342 {
343 str.erase(str.find_last_not_of(' ')+1,string::npos);
344 str.erase(0,str.find_first_not_of(' '));
345 }