把它們封裝一下,正在研究這個東西。
#ifndef _MYSOCKET_H_ #define _MYSOCKET_H_ #include <WinSock2.h> #include "Exception.h" class CMySocket { public: CMySocket(int type); void Bind(); inline int Sendto(char FAR* buf, int len, int flags, struct sockaddr FAR* to, int FAR* tolen); inline int Sendto(char FAR* buf, int len, int flags, const IpAddress& ipAddress); inline int Recvfrom(char FAR* buf, int len, int flags, struct sockaddr FAR* from, int FAR* fromlen); inline int Recvfrom(char FAR* buf, int len, int flags, const IpAddress& ipAddress); protected: SOCKET m_socket; }; class IpAddress { public: IpAddress() { memset(&address, 0, sizeof address); address.sin_family = AF_INET; address.sin_addr.S_un.S_addr = htonl(INADDR_ANY); } IpAddress(const char* ip, DWORD port) { ASSERT(ip != NULL); address.sin_family = AF_INET; address.sin_addr.S_un.S_addr = inet_addr(serverip); address.sin_port = htons(port); } void SetIp(const char* ip) { address.sin_addr.S_un.S_addr = inet_addr(ip); } void SetPort(DWORD port) { address.sin_port = htons(port); } void SetAddress(const char* ip, DWORD port) { ASSERT(ip != NULL); address.sin_addr.S_un.S_addr = inet_addr(ip); address.sin_port = htons(port); } const socketaddr_in* operator&() { return &address; } // const socketaddr socketaddr_in& GetRawElem() { return address; } private: socketaddr_in address; }; #endif #include "stdafx.h" #include "MySocket.h" #include <WinSock2.h> #pragma comment(lib, "ws2_32.lib") CMySocket::CMySocket(int type) { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("Windows sockets 2.2 startup"); throw Exception(""); } else { printf("Using %s (Status: %s)/n", wsaData.szDescription, wsaData.szSystemStatus); printf("with API versions %d.%d to %d.%d/n/n", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion), LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion)); } m_socket = socket(AF_INET, type, 0); if (m_socket < 0) { printf("create socket error"); throw Exception(""); } } void CMySocket::Bind() { sockaddr_in sin; sin.sin_addr.S_un.S_addr = INADDR_ANY; sin.sin_family = AF_INET; sin.sin_port = 0; if (bind(m_socket, (struct sockaddr*)&sin, sizeof(sin)) < 0) throw Exception("bind error"); } int CMySocket::Sendto(char FAR* buf, int len, int flags, struct sockaddr FAR* to, int FAR* tolen) { ASSERT((buf != NULL) && (to != NULL)); return sendto(m_socket, buf, len, flags, to, tolen); } int CMySocket::Sendto(char FAR* buf, int len, int flags, const IpAddress& ipAddress) { return sendto(m_socket, buf, len, flags, &ipAddress, sizeof(sockaddr_in)); } int CMySocket::Recvfrom(char FAR* buf, int len, int flags, struct sockaddr FAR* from, int FAR* fromlen) { ASSERT((buf != NULL) && (from != NULL)); return recvfrom(m_socket, buf, len, flags, from, fromlen); } int CMySocket::Recvfrom(char FAR* buf, int len, int flags, const IpAddress& ipAddress) { return recvfrom(m_socket, buf, len, flags, &ipAddress, sizeof(sockaddr_in)); } #include "stdafx.h" #include "Message.h" #include "MySocket.h" #include "ServerSocket.h" #include <cassert> #define SERVER_PORT 2280 class CServerSocket; class ClientSocket : public CMySocket { public: stUserListNode* GetUser(const char *username); void ConnectToServer(const char *username, const char *serverip); bool SendMessageTo(const char *UserName, const char *Message); private: UserList m_userList; CServerSocket* m_ServerSocket; }; stUserListNode* ClientSocket::GetUser(const char *username) { for(UserList::iterator UserIterator = m_userList.begin(); UserIterator != m_userList.end(); ++UserIterator) { if( strcmp( ((*UserIterator)->userName), username) == 0 ) return *UserIterator; } throw Exception("not find this user"); } void ClientSocket::ConnectToServer(const char *username, const char *serverip) { IpAddress serverAddr(serverip, SERVER_PORT); stMessage sendbuf; sendbuf.msgType = LOGIN_MSG; strncpy(sendbuf.msgBody.loginmember.userName, username, 10); Sendto((const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr*)&serverAddr,sizeof(serverAddr)); int usercount; int fromlen = sizeof(serverAddr); int iread = Recvfrom( (char *)&usercount, sizeof(int), 0, (sockaddr *)&serverAddr, &fromlen); if(iread <= 0) { throw Exception("Login error/n"); } // 登錄到服務端後,接收服務端發來的已經登錄的用戶的信息 cout<<"Have "<<usercount<<" users logined server:"<<endl; for(int i = 0;i<usercount;i++) { stUserListNode *node = new stUserListNode; Recvfrom( (char*)node, sizeof(stUserListNode), 0, (sockaddr *)&serverAddr, &fromlen); m_userList.push_back(node); cout << "Username:" << node->userName << endl; in_addr tmp; tmp.S_un.S_addr = htonl(node->ip); cout << "UserIP:" << inet_ntoa(tmp) << endl; cout << "UserPort:" << node->port << endl; cout << "" << endl; } } /*process user login*/ void ProcLogin() { ; } bool ClientSocket::SendMessageTo(const char *UserName, const char *Message) { char realmessage[256]; unsigned int UserIP; unsigned short UserPort; bool FindUser = false; for(UserList::iterator UserIterator = m_userList.begin(); UserIterator != m_userList.end(); ++UserIterator) { if(strcmp(((*UserIterator)->userName), UserName) == 0) { UserIP = (*UserIterator)->ip; UserPort = (*UserIterator)->port; FindUser = true; break; } } if(!FindUser) return false; strcpy(realmessage, Message); for(int i = 0; i < MAXRETRY; i++) { RecvedACK = false; IpAddress serverAddr(UserIP, UserPort); stP2PMessage MessageHead; MessageHead.iMessageType = P2PMESSAGE; MessageHead.iStringLen = (int)strlen(realmessage)+1; int isend = sendto(m_ServerSocket, (const char *)&MessageHead, sizeof(MessageHead), 0, (const sockaddr*)&serverAddr, sizeof(serverAddr)); isend = sendto(m_ServerSocket, (const char *)&realmessage, MessageHead.iStringLen, 0, (const sockaddr*)&serverAddr, sizeof(serverAddr)); // 等待接收線程將此標記修改 for(int j = 0; j < 10; j++) { if(RecvedACK) return true; else Sleep(300); } // 沒有接收到目標主機的迴應,認爲目標主機的端口映射沒有 // 打開,那麼發送請求信息給服務器,要服務器告訴目標主機 // 打開映射端口(UDP打洞) sockaddr_in server; server.sin_addr.S_un.S_addr = inet_addr(ServerIP); server.sin_family = AF_INET; server.sin_port = htons(SERVER_PORT); stMessage transMessage; transMessage.iMessageType = P2PTRANS; strcpy(transMessage.message.translatemessage.userName, UserName); sendto(m_ServerSocket, (const char*)&transMessage, sizeof(transMessage), 0, (const sockaddr*)&server, sizeof(server)); Sleep(100);// 等待對方先發送信息。 } return false; } // 接受消息線程 DWORD WINAPI RecvThreadProc(LPVOID lpParameter) { sockaddr_in serverAddr; int sinlen = sizeof(serverAddr); stP2PMessage recvbuf; CServerSocket *pServerSocket = (CServerSocket* )lpParameter; for(;;) { int iread = recvfrom(*serverSocket, (char *)&recvbuf, sizeof(recvbuf), 0, (sockaddr *)&serverAddr, &sinlen); if(iread<=0) { printf("recv error/n"); continue; } switch(recvbuf.iMessageType) { case P2PMESSAGE: { // 接收到P2P的消息 char *comemessage= new char[recvbuf.iStringLen]; int iread1 = recvfrom(*pServerSocket, comemessage, 256, 0, (sockaddr *)&serverAddr, &sinlen); comemessage[iread1-1] = '/0'; if(iread1 <= 0) throw Exception("Recv Message Error/n"); else { printf("Recv a Message:%s/n",comemessage); stP2PMessage sendbuf; sendbuf.iMessageType = P2PMESSAGEACK; sendto(*pServerSocket, (const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr*)&serverAddr, sizeof(serverAddr)); } delete []comemessage; break; } case P2PSOMEONEWANTTOCALLYOU: { // 接收到打洞命令,向指定的IP地址打洞 printf("Recv p2someonewanttocallyou data/n"); sockaddr_in serverAddr; serverAddr.sin_addr.S_un.S_addr = htonl(recvbuf.iStringLen); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(recvbuf.Port); // UDP hole punching stP2PMessage message; message.iMessageType = P2PTRASH; sendto(*pServerSocket, (const char *)&message, sizeof(message), 0, (const sockaddr*)&serverAddr, sizeof(serverAddr)); break; } case P2PMESSAGEACK: { // 發送消息的應答 RecvedACK = true; break; } case P2PTRASH: { // 對方發送的打洞消息,忽略掉。 //do nothing ... printf("Recv p2ptrash data/n"); break; } case GETALLUSER: { int usercount; int fromlen = sizeof(serverAddr); int iread = recvfrom(*pServerSocket, (char *)&usercount, sizeof(int), 0, (sockaddr *)&serverAddr, &fromlen); if(iread<=0) { throw Exception("Login error/n"); } ClientList.clear(); cout<<"Have "<<usercount<<" users logined server:"<<endl; for(int i = 0;i<usercount;i++) { stUserListNode *node = new stUserListNode; recvfrom(*pServerSocket, (char*)node, sizeof(stUserListNode), 0, (sockaddr *)&serverAddr, &fromlen); ClientList.push_back(node); cout<<"Username:"<<node->userName<<endl; in_addr tmp; tmp.S_un.S_addr = htonl(node->ip); cout<<"UserIP:"<<inet_ntoa(tmp)<<endl; cout<<"UserPort:"<<node->port<<endl; cout<<""<<endl; } break; } } } } #include "stdafx.h" #include "MySocket.h" class CServerSocket : public CMySocket { public: stUserListNode GetUser(const char* userName); int Run(); private: UserList m_userList; }; stUserListNode* CServerSocket::GetUser(const char* userName) { for (UserList::iterator iter = m_userList; iter != m_userList.end(); ++iter) { if (strcmp((*iter)->userName, userName) == 0) return *iter; } throw Exception("not find this user"); } int CServerSocket::Run() { try { //InitWinSock(); //SOCKET PrimaryUDP; m_socket = mksock(SOCK_DGRAM); sockaddr_in local; local.sin_family=AF_INET; local.sin_port= htons(SERVER_PORT); local.sin_addr.s_addr = htonl(INADDR_ANY); int nResult=bind(m_socket,(sockaddr*)&local,sizeof(sockaddr)); if(nResult == SOCKET_ERROR) throw Exception("bind error"); sockaddr_in sender; stMessage recvbuf; memset(&recvbuf,0,sizeof(stMessage)); // 開始主循環. // 主循環負責下面幾件事情: // 一:讀取客戶端登陸和登出消息,記錄客戶列表 // 二:轉發客戶p2p請求 for(;;) { int dwSender = sizeof(sender); int ret = Recvfrom( (char *)&recvbuf, sizeof(stMessage), 0, (sockaddr *)&sender, &dwSender); if(ret <= 0) { printf("recv error"); continue; } else { int messageType = recvbuf.iMessageType; switch(messageType){/*處理收到的用戶發來的消息*/ case LOGIN: { // 將這個用戶的信息記錄到用戶列表中 printf("has a user login : %s/n", recvbuf.message.loginmember.userName); stUserListNode *currentuser = new stUserListNode(); strcpy(currentuser->userName, recvbuf.message.loginmember.userName); currentuser->ip = ntohl(sender.sin_addr.S_un.S_addr); currentuser->port = ntohs(sender.sin_port); ClientList.push_back(currentuser); // 把已經登陸的客戶信息發送給新連的客戶 int nodecount = (int)ClientList.size(); Sendto((const char*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender)); for(UserList::iterator UserIterator=ClientList.begin(); UserIterator!=ClientList.end(); ++UserIterator) { Sendto((const char*)(*UserIterator), sizeof(stUserListNode), 0, (const sockaddr*)&sender, sizeof(sender)); } break; } case LOGOUT: { // 將此客戶信息刪除 printf("has a user logout : %s/n", recvbuf.message.logoutmember.userName); UserList::iterator removeiterator = NULL; for(UserList::iterator UserIterator=ClientList.begin(); UserIterator!=ClientList.end(); ++UserIterator) { if( strcmp( ((*UserIterator)->userName), recvbuf.message.logoutmember.userName) == 0 ) { removeiterator = UserIterator; break; } } if(removeiterator != NULL) ClientList.remove(*removeiterator); break; } case P2PTRANS: { // 某個客戶希望服務端向另外一個客戶發送一個打洞消息 printf("%s wants to p2p %s/n",inet_ntoa(sender.sin_addr),recvbuf.message.translatemessage.userName); stUserListNode node = GetUser(recvbuf.message.translatemessage.userName);//"TO" sockaddr_in remote; remote.sin_family=AF_INET; remote.sin_port= htons(node.port); remote.sin_addr.s_addr = htonl(node.ip); in_addr tmp; tmp.S_un.S_addr = htonl(node.ip); printf("the address is %s,and port is %d/n",inet_ntoa(tmp), node.port); stP2PMessage transMessage; transMessage.iMessageType = P2PSOMEONEWANTTOCALLYOU; transMessage.iStringLen = ntohl(sender.sin_addr.S_un.S_addr); transMessage.Port = ntohs(sender.sin_port); Sendto((const char*)&transMessage, sizeof(transMessage), 0, (const sockaddr *)&remote, sizeof(remote)); break; } case GETALLUSER: { int command = GETALLUSER; Sendto((const char*)&command, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender)); int nodecount = (int)ClientList.size(); Sendto((const char*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender)); for(UserList::iterator UserIterator=ClientList.begin(); UserIterator!=ClientList.end(); ++UserIterator) { Sendto((const char*)(*UserIterator), sizeof(stUserListNode), 0, (const sockaddr*)&sender, sizeof(sender)); } break; } } } } } catch(Exception &e) { printf(e.GetMessage()); return 1; } return 0; } #ifndef _MESSAGE_H_ #define _MESSAGE_H_ #include <list> using namespace std; enum MSG_TYPE { /*控制消息*/ LOGIN_MSG, LOGOUT_MSG, P2PTRANS_MSG, GETUSER_MSG, /*數據消息*/ DATA_MSG }; struct stLoginMessage { char userName[10]; char password[10]; }; // Client註銷時發送的消息 struct stLogoutMessage { char userName[10]; }; // Client向服務器請求另外一個Client(userName)向自己方向發送UDP打洞消息 struct stP2PTranslate { char userName[10]; }; // 客戶節點信息 struct stUserListNode { char userName[10]; unsigned int ip; unsigned short port; }; union MSG_BODY { stLoginMessage loginmember; stLogoutMessage logoutmember; stP2PTranslate translatemessage; stUserListNode user; }; struct stMessage { MSG_TYPE msgType; MSG_BODY msgBody; }; //====================================== // 下面的協議用於客戶端之間的通信 //====================================== #define P2PMESSAGE 100 // 發送消息 #define P2PMESSAGEACK 101 // 收到消息的應答 #define P2PSOMEONEWANTTOCALLYOU 102 // 服務器向客戶端發送的消息 // 希望此客戶端發送一個UDP打洞包 #define P2PTRASH 103 // 客戶端發送的打洞包,接收端應該忽略此消息 // 客戶端之間發送消息格式 struct stP2PMessage { int iMessageType; int iStringLen; // or IP address unsigned short Port; }; using namespace std; typedef list<stUserListNode *> UserList; #endif #ifndef _EXCEPTION_H_ #define _EXCEPTION_H_ #define EXCEPTION_MESSAGE_MAXLEN 256 #include "string.h" class Exception { private: char m_ExceptionMessage[EXCEPTION_MESSAGE_MAXLEN]; public: Exception(char *msg) { strncpy(m_ExceptionMessage, msg, EXCEPTION_MESSAGE_MAXLEN); } char *GetMessage() { return m_ExceptionMessage; } }; #endif
上篇從服務粒度角度進行了探討,本文繼續從服務內的分層角度探討。 本文的觀點源自我在學習與實踐過程中的深思熟慮,尚處於不斷探索和驗證的階段。希望能“拋磚引玉”,激發更多的討論與交流。讓我們共同進步,在探討與實證中尋求真知。 一、背景 應用
1.安全之Kerberos安全認證 1 Kerberos概述 1.1 什麼是Kerberos Kerberos是一種計算機網絡授權協議,用來在非安全網絡中,對個人通信以安全的手段進行身份認證。這個詞又指麻省理工學院爲這個協議開發的一套計算
本文介紹了 InnoDB 支持哪幾類表鎖,以及它們分別都用在什麼場景下,還介紹了其中兩類表鎖爲什麼要存在。 作者:操盛春,愛可生技術專家,公衆號『一樹一溪』作者,專注於研究 MySQL 和 OceanBase 源碼。 愛可生開源社區出品,
本文分享自華爲雲社區《手拉手入門springboot+kafka》,作者:QGS。 安裝kafka 啓動Kafka本地環境需Java 8+以上 Kafka是一種高吞吐量的分佈式發佈訂閱消息系統,它可以處理消費者在網站中的所有動作流數據。
作者:胡安祥 滿幫集團,作爲“互聯網+物流”的平臺型企業,一端承接託運人運貨需求,另一端對接貨車司機,提升貨運物流效率。2021 年美股上市,成爲數字貨運平臺上市第一股。根據公司年報,2021 年,超過 350 萬貨車司機在平臺上完成超 1
作者:Seata 社區 Part 1:歡迎大家報名 Apache Seata (incubating) 開源之夏 2024 課題 開源之夏 2024 學生報名期爲 4 月 30 日 - 6 月 3 日,歡迎報名 Apache Seata(i
圖片來源:國家航天局網站 近日,嫦娥六號任務還搭載了多個國際合作項目,包括法國的氡氣探測儀、歐空局(歐洲航天局(英文:European Space Agency),簡稱歐空局或ESA)的負離子探測儀、意大利的激光角反射鏡
轉載自tuoluzhe8521 導讀:通過簡化複雜的任務依賴關係, DolphinScheduler爲數據工程師提供了強大的工作流程管理和調度能力。在3.2.0版本中,DolphinScheduler帶來了一系列新功能和改進,使其在生產環
服務發現 在Spring cloud中,要注意區別服務和服務實例,這是兩個概念,一個微服務單元可以部署多個節點, 每個節點即一個服務實例,Spring cloud默認通過 spring.application.name 配置項來標識一個微服
本文作者: 張顯華、竇智浩、盧進文 與集中式架構相比,分佈式架構的系統複雜性呈指數級增長,混沌工程在信創轉型、分佈式架構轉型、小機下移等過程中有效保障了生產的穩定性。本文分享了 TiDB 分佈式數據庫在銀行核心業務系統落地中進行混沌測試的場
漏洞概述 漏洞服務: uhttpd 漏洞類型: 遠程命令執行 影響範圍: 1.0.4.26之前的NETGEAR R9000設備會受到身份驗證繞過的影響 解決建議: 更新版本 漏洞復現 操作環境: ubuntu:22.04 qemu-ve
1.redis未授權訪問漏洞 通過redis未授權訪問漏洞,會造成敏感信息泄露,甚至被利用直接控制服務器,其危害不言而喻。但是在實際工作中,發現一些開發人員和運維人員並不知道如何妥善配置。因此有了本文,對redis的配置,建議就是2條,一
1.hive 1.1 解壓 tar -zxf apache-hive-1.2.2-bin.tar.gz -C .. mv apache-hive-1.2.2-bin/ hive-1.2.2 1.2 修改配置
4月19日,Meta發佈了最新的大語言模型LLaMA3,具體包括一個 8B 模型和一個 70 B 模型,上下文長度支持8K, 被譽爲史上最強開源大語言模型,開源社區的“重磅炸彈”,效果直指GTP4。在諸多評測任務上,LLaMA3都有非常炸裂
操作系統Debian12 1. portainer 簡介 Portainer 是一個開源的輕量級容器管理工具,主要用於 Docker 和 Swarm 環境的可視化管理和操作。通過 Portainer,用戶可以通過簡潔易用的 Web UI