LocalSocket.h
lastError是个调试的方法,打印出当前的错误,省略了
List类,用STL自带那个,会有点问题,初步猜测是存值和存地址的问题,于是重新写了建德的列表类
list.h
example
#ifndef __SOCK_SERVER_H__ #define ___SOCK_SERVER_H__ #include "LocalSocket.h" #include <queue> #ifndef __LOCAL_SOCKET_SERVER__ #define __LOCAL_SOCKET_SERVER__ #include <windows.h> #include <string> #include <stdio.h> #include <vector> #include "list.h" #include "error.h" #define SYSTEM_MAX_PENDING_SOCKETS 8 #define BUFSIZE 0 using namespace std; typedef HANDLE NamePipe; class LocalSocketServer; class LocalSocket; struct Listener{ HANDLE handle; OVERLAPPED overlapped; bool connected; }; class LocalSocketServer{ public: LocalSocketServer(); ~LocalSocketServer(); bool listen(string name); void waitForNewConnection(int ms = INFINITE); void closeServer(); LocalSocket* nextPendingConnection(); int currentConnections(){ return connections.size(); } private: HANDLE eventHandle; string name; List<Listener> listeners; List<LocalSocket*> connections; bool addListener(); void newConnection(); void incomingConnection(NamePipe handle); }; class LocalSocket{ public: LocalSocket(HANDLE handle = NULL); ~LocalSocket(); bool connect(string name); string readAll(); bool waitReadReady(int ms = INFINITE); int writeAll(string data); bool isReadable(); void close(); int state(); private: HANDLE pipe; }; #endif
#include "LocalSocket.h" LocalSocketServer::LocalSocketServer(){ } LocalSocketServer::~LocalSocketServer(){ closeServer(); } bool LocalSocketServer::addListener(){ SECURITY_ATTRIBUTES sa; PSID worldSID = 0; PSECURITY_DESCRIPTOR pSD = new SECURITY_DESCRIPTOR; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = FALSE; //non inheritable handle, same as default sa.lpSecurityDescriptor = 0; //default securi InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(pSD, TRUE, 0, FALSE); HANDLE hToken = NULL; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)){ return false; } DWORD dwBufferSize = 0; GetTokenInformation(hToken, TokenUser, 0, 0, &dwBufferSize); PTOKEN_USER pTokenUser = (PTOKEN_USER)new BYTE[dwBufferSize]; memset(pTokenUser, 0, dwBufferSize); if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwBufferSize, &dwBufferSize)) { CloseHandle(hToken); return false; } dwBufferSize = 0; GetTokenInformation(hToken, TokenPrimaryGroup, 0, 0, &dwBufferSize); PTOKEN_PRIMARY_GROUP pTokenGroup = (PTOKEN_PRIMARY_GROUP)new BYTE[dwBufferSize]; memset(pTokenGroup, 0, dwBufferSize); if (!GetTokenInformation(hToken, TokenPrimaryGroup, pTokenGroup, dwBufferSize, &dwBufferSize)) { CloseHandle(hToken); return false; } CloseHandle(hToken); SID_IDENTIFIER_AUTHORITY WorldAuth = { SECURITY_WORLD_SID_AUTHORITY }; if (!AllocateAndInitializeSid(&WorldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &worldSID)) { return false; } //calculate size of ACL buffer DWORD aclSize = sizeof(ACL)+((sizeof(ACCESS_ALLOWED_ACE)) * 3); aclSize += GetLengthSid(pTokenUser->User.Sid) - sizeof(DWORD); aclSize += GetLengthSid(pTokenGroup->PrimaryGroup) - sizeof(DWORD); aclSize += GetLengthSid(worldSID) - sizeof(DWORD); aclSize = (aclSize + (sizeof(DWORD)-1)) & 0xfffffffc; PACL acl = (PACL)new BYTE[aclSize]; memset(acl, 0, aclSize); InitializeAcl(acl, aclSize, ACL_REVISION_DS); if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, pTokenUser->User.Sid)) { FreeSid(worldSID); return false; } if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, pTokenGroup->PrimaryGroup)) { FreeSid(worldSID); return false; } if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, worldSID)) { FreeSid(worldSID); return false; } SetSecurityDescriptorOwner(pSD, pTokenUser->User.Sid, FALSE); SetSecurityDescriptorGroup(pSD, pTokenGroup->PrimaryGroup, FALSE); if (!SetSecurityDescriptorDacl(pSD, TRUE, acl, FALSE)) { FreeSid(worldSID); printf("err:%s", lastError().c_str()); return false; } sa.lpSecurityDescriptor = pSD; listeners.push(Listener()); Listener& listener = listeners.last(); Listener* li = &listener; string pipeName = "\\\\.\\pipe\\"; pipeName.append(name); //将string转为wchar_t size_t origsize = pipeName.length() + 1; const size_t newsize = 100; size_t convertedChars = 0; wchar_t *wcstring = (wchar_t *)malloc(sizeof(wchar_t)*(pipeName.length() - 1)); mbstowcs_s(&convertedChars, wcstring, origsize, pipeName.c_str(), _TRUNCATE); listener.handle = CreateNamedPipe( wcstring, // pipe name PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access PIPE_TYPE_BYTE | // byte type pipe PIPE_READMODE_BYTE | // byte-read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances BUFSIZE, // output buffer size BUFSIZE, // input buffer size 1000, // client time-out &sa); free(wcstring); if (listener.handle == INVALID_HANDLE_VALUE){ listeners.pop(); return false; } memset(&listener.overlapped, 0, sizeof(listener.overlapped)); listener.overlapped.hEvent = eventHandle; if (!ConnectNamedPipe(listener.handle, &listener.overlapped)){ DWORD err = GetLastError(); switch (err) { case ERROR_IO_PENDING: listener.connected = false; break; case ERROR_PIPE_CONNECTED: listener.connected = true; SetEvent(eventHandle); break; default: CloseHandle(listener.handle); listeners.pop(); return false; } } else{ SetEvent(eventHandle); } return true; } void LocalSocketServer::closeServer(){ for (int i = 0; i < listeners.size(); ++i) CloseHandle(listeners[i].handle); listeners.clear(); if (eventHandle){ CloseHandle(eventHandle); } } bool LocalSocketServer::listen(string name){ this->name = name; eventHandle = CreateEvent(NULL, TRUE, FALSE, NULL); for (int i = 0; i < SYSTEM_MAX_PENDING_SOCKETS; ++i){ if (!addListener()){ return false; } } return true; } void LocalSocketServer::waitForNewConnection(int ms){ DWORD result = WaitForSingleObject(eventHandle, (ms == -1) ? INFINITE : ms); if (result != WAIT_TIMEOUT){ newConnection(); } } void LocalSocketServer::newConnection(){ DWORD dummy = 0; // Reset first, otherwise we could reset an event which was asserted // immediately after we checked the conn status. ResetEvent(eventHandle); // Testing shows that there is indeed absolutely no guarantee which listener gets // a client connection first, so there is no way around polling all of them. for (int i = 0; i < listeners.size();) { HANDLE handle = listeners[i].handle; Listener& listener = listeners[i]; BOOL lapRes = GetOverlappedResult(handle, &listener.overlapped, &dummy, FALSE); DWORD size = GetFileSize(handle, NULL); if (listener.connected || lapRes){ listeners.remove(i); addListener(); incomingConnection(handle); } else { if (GetLastError() != ERROR_IO_INCOMPLETE) { printf("err:%s\n", lastError().c_str()); return; } ++i; } } } LocalSocket* LocalSocketServer::nextPendingConnection(){ if (connections.size() == 0){ return NULL; } LocalSocket* sock = connections[0]; connections.remove(0); return sock; } void LocalSocketServer::incomingConnection(NamePipe handle){ LocalSocket* sock = new LocalSocket(handle); connections.push(sock); } LocalSocket::LocalSocket(NamePipe handle){ this->pipe = handle; } LocalSocket::~LocalSocket(){ close(); } bool LocalSocket::connect(string name){ string pipeName = "\\\\.\\pipe\\"; pipeName.append(name); int buffsize = 1024; //将string转为wchar_t size_t origsize = pipeName.length() + 1; const size_t newsize = 100; size_t convertedChars = 0; wchar_t *wcstring = (wchar_t *)malloc(sizeof(wchar_t)*(pipeName.length() - 1)); mbstowcs_s(&convertedChars, wcstring, origsize, pipeName.c_str(), _TRUNCATE); if (!WaitNamedPipe(wcstring, NMPWAIT_WAIT_FOREVER)) { printf("命名管道实例:\"%s\"不存在\n", pipeName.c_str()); return false; } pipe = CreateFile(wcstring, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (pipe == INVALID_HANDLE_VALUE){ printf("err: %s\n", lastError().c_str()); return false; } free(wcstring); return true; } bool LocalSocket::isReadable(){ DWORD filesize = GetFileSize(pipe, NULL); return filesize > 0; } int LocalSocket::state(){ DWORD bytes; if (PeekNamedPipe(pipe, NULL, 0, NULL, &bytes, NULL)){ return bytes; } return -1; } bool LocalSocket::waitReadReady(int ms /* = INFINITE */){ long count = 0; while (true) { if (state() == -1){ return false; } if (isReadable()){ return true; } Sleep(10); count++; if (ms != INFINITE && count > ms){ break; } } return false; } void LocalSocket::close(){ if (pipe != INVALID_HANDLE_VALUE){ DisconnectNamedPipe(pipe); CloseHandle(pipe); } } string LocalSocket::readAll(){ if (!pipe){ return ""; } int bufferSize = 1024; string result = string(""); char* buffer = new char[bufferSize + 1]; memset(buffer, 0, bufferSize); DWORD readSize = 0; bool isBreak = false; while (true){ if (!isReadable()){ break; } BOOL res = ReadFile(pipe, buffer, bufferSize, &readSize, NULL); result.append(buffer); memset(buffer, 0, bufferSize); if (res == FALSE){ printf("error: %s\n", lastError().c_str()); DWORD err = GetLastError(); switch (err){ case ERROR_IO_PENDING: break; case ERROR_MORE_DATA: isBreak = true; break; case ERROR_BROKEN_PIPE: case ERROR_PIPE_NOT_CONNECTED: break; default:break; } } if (isBreak){ break; } } delete[] buffer; return result; } int LocalSocket::writeAll(string data){ if (!pipe){ return 0; } DWORD writeSize = 0; BOOL res = WriteFile(pipe, data.c_str(), data.length(), &writeSize, NULL); if (res == FALSE){ printf("write file error!"); } return writeSize; }
lastError是个调试的方法,打印出当前的错误,省略了
List类,用STL自带那个,会有点问题,初步猜测是存值和存地址的问题,于是重新写了建德的列表类
list.h
#ifndef __LOCAL_LIST_H__ #define __LOCAL_LIST_H__ #include <stdio.h> #include <string.h> /** * 张彪的list类,类中的元素存储的是值 * @author norkts<norkts@gmail.com> */ template <class T> class List{ public: List(); ~List(); /** * 添加新元素 */ void append(T& t); /** * 移除新元素 */ void remove(int index); /** * 添加新元素 */ void push(T& t); /** * 移除最好一个元素 */ void pop(); T& operator [](int index); /** * 获取最后一个元素 */ T& last(); /** * 列表大小 */ int size(); int length(); /** * 清空列表 */ void clear(); private: T** m_datas; //数据指针 int m_size; //列表元素数目 int m_maxSize; //元素最大个数 }; template <class T> List<T>::List(){ m_maxSize = 1000; m_size = 0; m_datas = new T*[m_maxSize](); } template <class T> List<T>::~List(){ clear(); } template <class T> void List<T>::append(T& t){ if (m_size >= m_maxSize){ m_maxSize = m_maxSize * 2; //扩展最大个数 T** newDatas = new T*[m_maxSize * 2](); memcpy(newDatas, m_datas, sizeof(m_datas)); delete[] m_datas; m_datas = newDatas; } *(m_datas + m_size) = new T(); memcpy(*(m_datas + m_size), &t, sizeof(T)); //复制值 m_size++; } template <class T> int List<T>::size(){ return m_size; } template <class T> int List<T>::length(){ return size(); } template <class T> void List<T>::remove(int index){ T *item = *(m_datas + index); delete item; memcpy(m_datas + index, m_datas + index + 1, sizeof(T*)* (m_size - index));//将后面的元素前移 m_size--; } template <class T> T& List<T>::operator [](int index){ return **(m_datas + index); } template <class T> void List<T>::push(T& t){ return append(t); } template <class T> void List<T>::pop(){ return remove(size() - 1); } template <class T> T& List<T>::last(){ return **(m_datas + size() - 1); } template <class T> void List<T>::clear(){ delete[] m_datas; } #endif
example
int main(){ LocalSocketServer server; server.listen("fgt-js-message"); while (true){ server.waitForNewConnection(); if (server.currentConnections() > 0){ LocalSocket* sock = server.nextPendingConnection(); while (true) { sock->waitReadReady(); string data = sock->readAll(); printf("%s\n", data.c_str()); if (sock->state() == -1){ break; } } sock->close(); } } }
相关推荐
一个C++高性能http服务端和客户端库,个C++高性能http服务端和客户端库一个C++高性能http服务端和客户端库 一个C++高性能http服务端和客户端库 一个C++高性能http服务端和客户端库 一个C++高性能http服务端和客户端...
新项目基于TCP Socket实现的多线程聊天室程序c++源码(含服务端+客户端).zip新项目基于TCP Socket实现的多线程聊天室程序c++源码(含服务端+客户端).zip新项目基于TCP Socket实现的多线程聊天室程序c++源码(含服务端+...
本资源提供的“c++ tcp 程序(含服务端和客户端源码)”是一个学习和实践C++ TCP编程的绝佳示例。 首先,我们来深入理解TCP协议。TCP通过三次握手建立连接,确保数据传输前双方已经准备好。在数据传输过程中,TCP会...
基于C++和POLL的服务端和客户端源码(含项目说明+详细注释).zip LINUX网络编程部分开源项目学习和改进 ## 一、基于C++和POLL的服务端和客户端   1)文献来源:《Linux高性能服务器编程》——游双著;\ &...
标题中的“udp 服务端和客户端,c++”指的是使用C++编程语言实现UDP(User Datagram Protocol)协议的服务端和客户端程序。UDP是传输层的一种无连接、不可靠的协议,常用于实时数据传输,如视频流、语音通话等场景。...
本文将深入探讨标题和描述中提到的"一个C++高性能http服务端和客户端库,支持http2协议,http1长连接"这一主题。 首先,HTTP(超文本传输协议)是互联网上应用最为广泛的一种网络协议,它定义了客户端和服务器之间...
在C++中,服务端和客户端的实现则需要更底层的网络API,如套接字(Sockets)库。在C++中,可以使用标准模板库(STL)和Boost库来辅助实现,但基本的网络操作仍依赖于系统级别的socket接口。服务端会创建一个监听套接字...
本文将深入探讨如何使用C++实现HTTP POST服务端和客户端,特别是涉及JSON格式的数据交换。 首先,HTTP POST是Web服务中最常用的方法之一,用于向服务器发送数据。在C++中实现HTTP POST,你需要理解HTTP协议的基本...
通过学习这个实例,开发者不仅可以理解 C++ Socket 编程的基本原理,还能掌握服务端和客户端的通信流程,为更复杂的网络应用开发打下基础。实践中,还可以尝试实现更丰富的功能,比如加密通信、断线重连、数据压缩等...
根据提供的文件信息,我们可以深入探讨如何使用C++实现网络编程中的服务端与客户端,并通过具体的代码片段来理解其中的关键概念和技术细节。 ### C++ 实现网络编程基础 #### Socket 编程简介 Socket编程是实现...
本篇将深入探讨如何使用Visual Studio C++进行TCP网络编程,涵盖服务端和客户端的实现。 一、TCP协议简介 TCP是一种面向连接的传输层协议,它确保了数据的顺序传输和错误检查,通过三次握手建立连接,并在四次挥手...
此代码用c++实现了http客户端的编写,其中包括了多字节转utf8(已在ExecuteRequest函数中实现,不用再引用所给的编码转换),get和post两种请求方式,后面有json数据的解析以及实现,详情可去博客...
本实例提供了C++实现的服务端(server.cpp)和客户端(client.cpp),让我们深入探讨这个主题。 首先,C++中的Socket编程通常涉及两个主要部分:服务器端和客户端。服务器端负责监听特定的端口,等待客户端连接,并处理...
本压缩包提供了一份在Linux环境下实现TCP通信的示例代码,包括服务端和客户端的实现。 服务端实现: 服务端程序是TCP通信的起点,它创建一个监听套接字,并绑定到特定的IP地址和端口号上。通过调用`socket()`函数...
用C++实现的websocket的服务端和客户端代码
该项目是基于C++的电子邮件系统服务端与客户端设计源码,共包含73个文件,其中包括18个头文件(.h)、15个C++源文件(.cc)、8个C++源文件(.cpp)、6个Code::Blocks项目文件(.cbp)、6个依赖文件(.depend)、6个...
下面将详细解释C++中实现UDP服务端和客户端程序的关键知识点。 首先,了解UDP的基本概念至关重要。与TCP(传输控制协议)不同,UDP不保证数据包的顺序、完整性和可靠性,而是以尽可能快的速度发送数据,因此适用于...
基于C++和QtWebApp的文件快传Windows HTTP项目完整源码(含服务端+客户端)+项目说明.zip基于C++和QtWebApp的文件快传Windows HTTP项目完整源码(含服务端+客户端)+项目说明.zip基于C++和QtWebApp的文件快传Windows ...