赞
踩
服务端代码,由于recv和send用的是阻塞函数,考虑用多线程开两个子线程分别读写
服务端:
头文件Server.h
- #include <WinSock2.h>
- #include <iostream>
- #include <vector>
- #pragma comment(lib,"ws2_32.lib")
-
- using namespace std;
-
- #define PORT 7777
-
- DWORD WINAPI SendMessage(LPVOID LParam)
- {
- SOCKET* sockClient = (SOCKET*)LParam;
-
- //登录初始化
- char recvBuf[100];
- memset(recvBuf,0,sizeof(recvBuf));
- char sendbuf[] = "服务器连接成功!欢迎... ...\n输入bye退出";
- int ret = send(*sockClient,sendbuf,sizeof(sendbuf),0);
- if(ret == SOCKET_ERROR)
- {
- cout << "Send data failed ... ..." <<endl;
- return -1;
- }
-
- while(strcmp(sendbuf,"bye")!=0)
- {
- //============== send() ==============
- memset(sendbuf,0,sizeof(sendbuf));
- cin >> sendbuf;
- ret = send(*sockClient,sendbuf,sizeof(sendbuf),0);
- if(ret == SOCKET_ERROR)
- {
- cout << "Send data failed ... ..." <<endl;
- return -2;
- }
- }
- return NULL;
- }
-
- DWORD WINAPI ReceiveMessage(LPVOID LParam)
- {
- SOCKET* sockClient = (SOCKET*)LParam;
-
- char receivebuf[2048];
-
-
- int ret = 0;
- while(strcmp(receivebuf,"bye")!=0)
- {
- //============== recv() ==============
- memset(receivebuf,0,sizeof(receivebuf));
- ret = recv(*sockClient,receivebuf,sizeof(receivebuf),0);
- if(ret >=0 )
- {
- //cout << "########## receive data(" << ret << " byte) ##########" <<endl;
- cout << receivebuf <<endl;
- }
- }
- return NULL;
- }
-
- class CServer
- {
- public:
- CServer(int nPort=PORT);
- ~CServer();
-
- int Socket();
- int Bind();
- int Listen();
- int Accept();
- int CreateConversation();
-
- HANDLE GetSendHandle();
- HANDLE GetReceiveHandle();
-
- protected:
- private:
- HANDLE m_hSendThread;
- HANDLE m_hReceiveThread;
- DWORD m_dSendThreadId;
- DWORD m_dReceiveThreadId;
- int m_nPort;
- SOCKET sockSrv;
- SOCKADDR_IN m_addrSrv;
-
- //客户端信息
- SOCKET sockClient;
- SOCKADDR_IN m_addrClient;
- };
Server.cpp
- #include "Server.h"
- #include <Windows.h>
-
-
- DWORD WINAPI CONNECT_POOLING(LPVOID lpParam)
- {
- return 0;
- }
-
- CServer::CServer(int nPort)
- {
- m_nPort = nPort;
- m_hSendThread = NULL;
- m_hReceiveThread = NULL;
-
- //初始化IP和port
- m_addrSrv.sin_family = AF_INET;
- m_addrSrv.sin_port = htons(m_nPort);//1024以上端口号
- m_addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
- }
-
- CServer::~CServer()
- {
- m_nPort = 0;
- CloseHandle(m_hSendThread);
- CloseHandle(m_hReceiveThread);
- closesocket(sockClient);
- closesocket(sockSrv);
- WSACleanup();
- }
-
- int CServer::Socket()
- {
- WSADATA data;
- int ret = WSAStartup(MAKEWORD(2,2),&data);
- //Debug
- /*cout << "Initialization return " << ret << endl;*/
-
- if(ret)
- {
- cout << "Socket initialization failed: " << WSAGetLastError() << "... ..." << endl;
- return -1;
- }
-
- sockSrv = socket(AF_INET,SOCK_STREAM,0);
- if (SOCKET_ERROR == sockSrv)
- {
- cout << "Socket create failed: " << WSAGetLastError() << "... ..." << endl;
- return -2;
- }
- return ret;
- }
-
- int CServer::Bind()
- {
- //SOCKET sock = sockSrv;
- //============== bind() ==============
- int ret = bind(sockSrv,(LPSOCKADDR)&m_addrSrv,sizeof(SOCKADDR_IN));
-
- //Debug
- /*cout << "bind return " << ret << endl;*/
-
- if(ret)
- {
- cout << "Socket bind failed: " << WSAGetLastError() << "... ..." << endl;
- return -2;
- }
- else
- {
- cout << "Socket bind succeed! " << endl;
- }
-
- return ret;
- }
-
- int CServer::Listen()
- {
- //============== listen() ==============
- int ret = listen(sockSrv,10);
-
- if(ret == SOCKET_ERROR)
- {
- cout << "Socket listen failed: " << WSAGetLastError() << "... ..." << endl;
- return -3;
- }
-
- //begin to listen
- cout << "Server start successfully ... ... Begin listening on "<< m_nPort << endl;
-
- return ret;
- }
-
- int CServer::Accept()
- {
- int len = sizeof(SOCKADDR);
- //等待客户端connect请求
- //============== accept() ==============
- sockClient = accept(sockSrv,(LPSOCKADDR)&m_addrClient,&len);
-
- if (sockClient == SOCKET_ERROR)
- {
- cout << "Build connection failed: " << WSAGetLastError() << "... ..." << endl;
- return -1;
- }
- else
- {
- printf("Server(%s:%d) build connection with Client at %s:%d\n",
- inet_ntoa(m_addrSrv.sin_addr),htons(m_addrSrv.sin_port),
- inet_ntoa(m_addrClient.sin_addr),htons(m_addrClient.sin_port));
- }
- return 0;
- }
-
- int CServer::CreateConversation()
- {
- m_hSendThread = CreateThread(NULL,0,SendMessage,&sockClient,0,&m_dSendThreadId);
- m_hReceiveThread = CreateThread(NULL,0,ReceiveMessage,&sockClient,0,&m_dReceiveThreadId);
-
- return 0;
- }
-
- HANDLE CServer::GetSendHandle()
- {
- return m_hSendThread;
- }
-
- HANDLE CServer::GetReceiveHandle()
- {
- return m_hReceiveThread;
- }
-
-
- int Initialize()
- {
- WSADATA data;
- int ret = WSAStartup(MAKEWORD(2,2),&data);
- //Debug
- /*cout << "Initialization return " << ret << endl;*/
-
- if(ret)
- {
- cout << "Socket initialization failed: " << WSAGetLastError() << "... ..." << endl;
- return -1;
- }
- return 0;
- }
-
- int Start_Server()
- {
- int ret = 0;
- //============== socket() ==============
- SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);
- unsigned long pcmd = NULL;
-
- //Debug
- /*ret = sockSrv;
- cout << "socket return " << ret << endl;
- if(SOCKET_ERROR == ret)
- {
- cout << "Socket create failed: " << WSAGetLastError() << "... ..." << endl;
- }*/
-
- //初始化IP和port
- SOCKADDR_IN addrSrv;
- addrSrv.sin_family = AF_INET;
- addrSrv.sin_port = htons(PORT);//1024以上端口号
- addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
-
- //============== bind() ==============
- ret = bind(sockSrv,(LPSOCKADDR)&addrSrv,sizeof(SOCKADDR_IN));
- //Debug
- /*cout << "bind return " << ret << endl;*/
-
- if(ret)
- {
- cout << "Socket bind failed: " << WSAGetLastError() << "... ..." << endl;
- return -2;
- }
-
- //============== listen() ==============
- ret = listen(sockSrv,10);
- if(ret == SOCKET_ERROR)
- {
- cout << "Socket listen failed: " << WSAGetLastError() << "... ..." << endl;
- return -3;
- }
- //客户端信息
- SOCKADDR_IN addrClient;
- int len = sizeof(SOCKADDR);
- //begin to listen
- cout << "Server start successfully ... ... Begin listening" << endl;
- while(1)
- {
- //等待客户端connect请求
- //============== accept() ==============
- SOCKET sockConn = accept(sockSrv,(LPSOCKADDR)&addrClient,&len);
- //ioctlsocket(sockConn,FIONBIO,&pcmd);
- if (sockConn == SOCKET_ERROR)
- {
- cout << "Build connection failed: " << WSAGetLastError() << "... ..." << endl;
- break;
- }
- printf("Server(%s:%d) build connection with Client at %s:%d\n",
- inet_ntoa(addrSrv.sin_addr),htons(addrSrv.sin_port),
- inet_ntoa(addrClient.sin_addr),htons(addrClient.sin_port));
-
- //登录初始化
- char recvBuf[100];
- memset(recvBuf,0,sizeof(recvBuf));
- char buf[] = "服务器连接成功!欢迎登录... ...\n";
- ret = send(sockConn,buf,sizeof(buf),0);
- if(ret == SOCKET_ERROR)
- {
- cout << "Send data failed ... ..." <<endl;
- break;
- }
-
- while(recvBuf != "bye" || buf != "bye")
- {
- memset(recvBuf,0,sizeof(recvBuf));
- //============== send() ==============
- char buf[100];
- memset(buf,0,sizeof(buf));
- cin >> buf;
- ret = send(sockConn,buf,sizeof(buf),0);
- if(ret == SOCKET_ERROR)
- {
- cout << "Send data failed ... ..." <<endl;
- break;
- }
-
-
- //============== recv() ==============
- ret = recv(sockConn,recvBuf,sizeof(recvBuf),0);
- cout << "########## receive data(" << ret << " byte) ##########" <<endl;
- cout << recvBuf <<endl;
-
- }
-
- //关闭用于和客户端收发数据而建立的socket
- //Linux下一切皆文件,直接用文件操作函数close()关闭socket即可
- //============== closesocket() ==============
- closesocket(sockConn);
- }
- //关闭用于监听客户端连接请求的socket
- //============== closesocket() ==============
- closesocket(sockSrv);
- WSACleanup();
-
- cout << "Good Bye!" << endl;
-
- return 0;
- }
-
- int main()
- {
-
- /*老版读写阻塞
- Initialize();
- Start_Server();
- system("pause");
- */
-
-
-
- //Winsock服务初始化、创建套接字
- cout << "请输入服务器监听端口:" << endl;
- int nPort;
- cin >> nPort;
- CServer oServer = CServer(nPort);
- oServer.Socket();
-
- //绑定套接字
- oServer.Bind();
-
- //监听套接字
- oServer.Listen();
-
- //等待连接
- oServer.Accept();
-
- //建立会话
- oServer.CreateConversation();
-
- /*Initialize();
- Start_Server();*/
- WaitForSingleObject(oServer.GetSendHandle(),INFINITE);
- WaitForSingleObject(oServer.GetReceiveHandle(),INFINITE);
- //system("pause");
-
- return 0;
- }
客户端:
Client.h
- #include <stdio.h>
- #include <WinSock2.h>
- #include <iostream>
- #pragma comment(lib,"ws2_32.lib")
- using namespace std;
-
- #define PORT 7777
-
- DWORD WINAPI SendMessage(LPVOID LParam)
- {
- SOCKET* sockClient = (SOCKET*)LParam;
-
- char sendbuf[2048];
-
- while(strcmp(sendbuf,"bye")!=0)
- {
- //========== send() ==========
- memset(sendbuf,0,sizeof(sendbuf));
- cin >> sendbuf;
- send(*sockClient,sendbuf,sizeof(sendbuf),0);
- }
- return NULL;
- }
- DWORD WINAPI ReceiveMessage(LPVOID LParam)
- {
- SOCKET* sockClient = (SOCKET*)LParam;
-
- char receivebuf[2048];
-
- int ret = 0;
- while(strcmp(receivebuf,"bye")!=0)
- {
- //========== recv() ==========
- memset(receivebuf,0,sizeof(receivebuf));
- ret = recv(*sockClient,receivebuf,sizeof(receivebuf),0);
- if(ret >= 0)
- {
- //cout << "Receiving from the host " << ret << " bytes ... ..." <<endl;
- cout << receivebuf <<endl;
- }
- }
- return NULL;
- }
-
- class CClient
- {
- public:
- CClient(const char* ip = "127.0.0.1",int nPort = PORT);
- ~CClient();
-
- int Socket();
- int Connect();
- int CreateConversation();
-
- HANDLE GetSendHandle();
- HANDLE GetReceiveHandle();
-
- int SetPort(int nPort);
- int GetPort();
-
- int SetIP(char ip[]);
- const char* GetIP();
-
- protected:
- private:
- HANDLE m_hSendThread;
- HANDLE m_hReceiveThread;
- DWORD m_dSendThreadId;
- DWORD m_dReceiveThreadId;
- int m_nPort;
- const char* m_IP;
- SOCKET sockClient;
- SOCKADDR_IN m_sockAddr;
- };
-
- //Winsock服务初始化
- int Initialize();
-
- //建立、启动客户端
- int Start_Client();
Client.cpp
- #include "Client.h"
-
-
- CClient::CClient(const char* ip,int nPort)
- {
- m_IP = ip;
- m_nPort = nPort;
- m_hSendThread = NULL;
- m_hReceiveThread = NULL;
-
- //初始化IP和port
- m_sockAddr.sin_family = AF_INET;
- m_sockAddr.sin_port = htons(m_nPort);//1024以上端口号
- m_sockAddr.sin_addr.S_un.S_addr = inet_addr(m_IP);
- }
-
- CClient::~CClient()
- {
- m_nPort = 0;
- CloseHandle(m_hSendThread);
- CloseHandle(m_hReceiveThread);
- closesocket(sockClient);
- WSACleanup();
- }
-
- int CClient::Socket()
- {
- WSADATA data;
- int ret = WSAStartup(MAKEWORD(2,2),&data);
- //Debug
- /*cout << "Initialization return " << ret << endl;*/
-
- if(ret)
- {
- cout << "Socket initialization failed: " << WSAGetLastError() << "... ..." << endl;
- return -1;
- }
-
- sockClient = socket(AF_INET,SOCK_STREAM,0);
- if (SOCKET_ERROR == sockClient)
- {
- cout << "Socket create failed: " << WSAGetLastError() << "... ..." << endl;
- return -2;
- }
- return ret;
- }
-
- int CClient::Connect()
- {
- int ret = connect(sockClient,(sockaddr *)&m_sockAddr,sizeof(m_sockAddr));
- if(ret == INVALID_SOCKET)
- {
- cout << "Connect to the host(" << this->GetIP() << ":" << this->GetPort() << ")failed: " << WSAGetLastError() << "... ..." << endl;
- return -3;
- }
- else
- {
- cout << "Connect to the host(" << this->GetIP() << ":" << this->GetPort() << ")succeed! " << endl;
- }
- return ret;
- }
-
- int CClient::CreateConversation()
- {
- m_hReceiveThread = CreateThread(NULL,0,ReceiveMessage,&sockClient,0,&m_dReceiveThreadId);
- m_hSendThread = CreateThread(NULL,0,SendMessage,&sockClient,0,&m_dSendThreadId);
- return NULL;
- }
-
- HANDLE CClient::GetSendHandle()
- {
- return m_hSendThread;
- }
-
- HANDLE CClient::GetReceiveHandle()
- {
- return m_hReceiveThread;
- }
-
- int CClient::SetPort(int nPort)
- {
- m_nPort = nPort;
- m_sockAddr.sin_port = htons(m_nPort);
- return m_nPort;
- }
-
- int CClient::GetPort()
- {
- return m_nPort;
- }
-
- int CClient::SetIP(char ip[])
- {
- m_IP = ip;
- m_sockAddr.sin_addr.S_un.S_addr = inet_addr(m_IP);
- return 0;
- }
-
- const char* CClient::GetIP()
- {
- return m_IP;
- }
-
- int Start_Client()
- {
- DWORD thread_id = 0;
- HANDLE hThread = CreateThread(NULL,0,SendMessage,NULL,0,&thread_id);
- CloseHandle(hThread);
-
-
- int ret = 0;
- char buff[2048];
- memset(buff,0,sizeof(buff));
-
- //初始化IP和port
- SOCKADDR_IN addrSrv;
- addrSrv.sin_family = AF_INET;
- addrSrv.sin_port = htons(PORT);//1024以上端口号
- addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
-
- //========== socket() ==========
- SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);
- if (SOCKET_ERROR == sockClient)
- {
- cout << "Socket create failed: " << WSAGetLastError() << "... ..." << endl;
- return -2;
- }
- //========== connect() ==========
- ret = connect(sockClient,(sockaddr *)&addrSrv,sizeof(addrSrv));
- if(ret == INVALID_SOCKET)
- {
- cout << "Connect to the host failed: " << WSAGetLastError() << "... ..." << endl;
- return -3;
- }
- else
- {
- char buf[2048];
- memset(buf,0,sizeof(buf));
- while(buff != "bye" || buf != "bye")
- {
- memset(buf,0,sizeof(buf));
- memset(buff,0,sizeof(buff));
- //========== recv() ==========
- ret = recv(sockClient,buff,sizeof(buff),0);
- cout << "Receiving from the host " << ret << " bytes ... ..." <<endl;
- cout << buff <<endl;
- //========== send() ==========
-
- cin >> buf;
- send(sockClient,buf,sizeof(buf),0);
- }
- }
-
- //关闭用于监听客户端连接请求的socket
- //============== closesocket() ==============
- closesocket(sockClient);
- WSACleanup();
-
- return 0;
- }
-
- int main()
- {
-
- /*老板读写阻塞
- Initialize();
- Start_Client();
- */
-
-
- //Winsock服务初始化、创建套接字
- char ip[24];
- cout << "请输入远程服务器IP:" << endl;
- cin >> ip;
-
- int nPort;
- cout << "请输入远程服务器端口:" << endl;
- cin >> nPort;
- CClient oClient = CClient(ip,nPort);
- oClient.Socket();
-
- //建立连接
- while(oClient.Connect() != 0)
- {
- //连接失败重新建立连接
- cout << "连接失败,请确认IP地址及端口" << endl;
- cout << "IP地址:" << ip << "是否正确?" << endl;
-
- char answer[8];
- memset(answer,0,sizeof(answer));
- while(strcmp(answer,"Y") != NULL && strcmp(answer,"N") != NULL && strcmp(answer,"y") != NULL && strcmp(answer,"n") != NULL)
- {
- memset(answer,0,sizeof(answer));
- cout << "Y/N?" << endl;
- cin >> answer;
- if(strcmp(answer,"Y") == NULL || strcmp(answer,"y") == NULL)
- {
- break;
- }
- else if(strcmp(answer,"N") == NULL || strcmp(answer,"n") == NULL)
- {
- cout << "请输入正确的IP:" << endl;
- cin >> ip;
- oClient.SetIP(ip);
- }
- }
-
- cout << "远程端口:" << nPort << "是否正确?" << endl;
- memset(answer,0,sizeof(answer));
- while(strcmp(answer,"Y") != 0 && strcmp(answer,"N") != 0 && strcmp(answer,"y") != 0 && strcmp(answer,"n") != 0)
- {
- memset(answer,0,sizeof(answer));
- cout << "Y/N?" << endl;
- cin >> answer;
- if(strcmp(answer,"Y") == NULL || strcmp(answer,"y") == NULL)
- {
- break;
- }
- else if(strcmp(answer,"N") == NULL || strcmp(answer,"n") == NULL)
- {
- cout << "请输入正确的端口:" << endl;
- cin >> nPort;
- oClient.SetPort(nPort);
- }
- }
- }
-
- //建立会话
- oClient.CreateConversation();
-
- WaitForSingleObject(oClient.GetSendHandle(),INFINITE);
- WaitForSingleObject(oClient.GetReceiveHandle(),INFINITE);
-
- //system("pause");
-
- return 0;
- }
本地IP测试连接成功,但通过公网IP连不上,没有开端口映射,可以考虑在路由器上设置,以下采用nat123创建了内网穿透。
此方式建的p2p转发需要在客户端机子上再开一个访问者
域名和端口填上以后添加访问,等连接建立上就可以用客户端和服务端建立通讯了(因为是用别的公网服务器转发的,因此IP并非本机外网IP而是用上图的转发IP:127.15.83.54)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。