ModSocket是一套通用的輕量級TCP 通信框架,包含服務端組件、客戶端組件,適用於各種不同套用場景的TCP通信系統,提供C/C++、E(易語言)、Python等程式語言接口。ModSocket對通信層完全封裝;ModSocket提供基於事件通知模型的API接口,能非常簡單的整合到新舊應用程式中。
基本介紹
- 中文名:ModSocket
- 外文名:ModSocket
- 適 用:Windows
ModSocket.h,C++實例,
ModSocket.h
#pragma once#define _WINSOCK_DEPRECATED_NO_WARNINGS 0#include<WinSock2.h>#include <thread>#include <iostream>using namespace std;#pragma comment (lib,"ws2_32")#pragma comment (lib,"winmm")#pragma comment(lib, "Ws2_32.lib")//客戶端class modble_client {private: WSADATA wsaData; SOCKET sHost; SOCKADDR_IN servAddr; //內部訊息處理 void cl(void Received(char* data), void discontinue(const char* err)) { char recv_buf[MAXBYTE] = { 0 }; int recv_len; while (1) { recv_len = recv(sHost, recv_buf, MAXBYTE, 0); if (recv_len < 0) { discontinue("伺服器主動下線"); break; } else { Received(recv_buf); } } }public: //服務端IP,服務端port,是否阻塞,數據到達事件,下線事件 void init(const char* ip, int port, bool isok, void Received(char* data), void discontinue(const char* err)) { if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { discontinue("Winsock load faild!"); return; } // 伺服器套接字 sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sHost == INVALID_SOCKET) { discontinue("socket faild!"); return; } servAddr.sin_family = AF_INET; // 注意 當把客戶端程式發到別人的電腦時 此處IP需改為伺服器所在電腦的IP servAddr.sin_addr.S_un.S_addr = inet_addr(ip); servAddr.sin_port = htons(port); // 連線伺服器 if (connect(sHost, (LPSOCKADDR)& servAddr, sizeof(servAddr)) == SOCKET_ERROR) { discontinue("connect faild!"); return; } if (isok) { cl(Received, discontinue); } else { thread t123(&modble_client::cl, this, Received, discontinue); t123.detach(); } return; } void ssend(const char* data) { send(sHost, data, MAXBYTE, 0); } void exit() { closesocket(sHost); WSACleanup(); }};/*******************************************************************************************///*****************************以下為modsocket_server*******************************************//服務端class modsocket_server {private: WSADATA wsaData; sockaddr_in addr; SOCKET s; //理論上可以同時線上5000人 SOCKET clientSock[5000]; SOCKADDR clientAddr[5000]; sockaddr_in clientsa[5000]; int uid = 0; /* 內部訊息處理 參數一:數據到達事件 參數二:用戶斷開事件 參數三:用戶socket結構體 參數四:用戶info結構體 */ void cl(void Received(SOCKET, sockaddr_in, char*), void leave(SOCKET, sockaddr_in), SOCKET xxyh, sockaddr_in yhinfo) { //不斷的接收客戶端傳送過來的信息 while (TRUE) { char buff[MAXBYTE] = { 0 }; //接收線上客戶端發來的數據 int i ; i = recv(xxyh, buff, MAXBYTE, 0); if (i >= 0 ) { //事件通知::接收數據 Received(xxyh, yhinfo, buff); } else { //事件通知::客戶斷開 closesocket(xxyh); leave(xxyh, yhinfo); //uid--; return; } } } /* 內部事件處理 參數一:用戶進入事件 參數二:數據到達事件 參數三:用戶斷開事件 參數四:連線埠 */ void forecho(void into(SOCKET, sockaddr_in), void Received(SOCKET, sockaddr_in, char*), void leave(SOCKET, sockaddr_in),void error(const char*), int port) { if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { error("Winsock load faild!"); return; } s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { error("socket faild!"); return; } addr.sin_addr.S_un.S_addr = inet_addr("0.0.0.0"); addr.sin_port = htons(port); addr.sin_family = PF_INET; bind(s, (SOCKADDR*)& addr, sizeof(SOCKADDR)); if (listen(s, 1)) { error("監聽失敗,可能連線埠已經存在,請嘗試更換..."); return; } int nSize = sizeof(SOCKADDR); while (TRUE) { clientSock[uid] = accept(s, (SOCKADDR*)& clientAddr, &nSize); //事件通知::用戶進入 int len = sizeof(clientsa[uid]); getpeername(clientSock[uid], (struct sockaddr*) & clientsa[uid], &len); into(clientSock[uid], clientsa[uid]); //訊息處理 //cl( Received, leave); thread t123(&modsocket_server::cl, this, Received, leave, clientSock[uid], clientsa[uid]); t123.detach(); uid++; } }public: /* 初始化事件 參數一:用戶進入事件 參數二:數據到達事件 參數三:用戶斷開事件 參數四:錯誤處理 參數無:連線埠 參數六:是否阻塞 */ void init(void into(SOCKET, sockaddr_in), void Received(SOCKET, sockaddr_in, char*), void leave(SOCKET, sockaddr_in),void error(const char*), int port, bool isok) { if (isok) { //阻塞模式 forecho(into, Received, leave,error, port); } else { //非阻塞模式 thread t123a(&modsocket_server::forecho, this, into, Received, leave, error, port); t123a.detach(); } } //獲取用戶遠程IP char* get_user_ip(SOCKET client) { sockaddr_in sa; int len = sizeof(sa); getpeername(client, (struct sockaddr*) & sa, &len); return inet_ntoa(sa.sin_addr); } //獲取用戶遠程連線埠 int get_user_port(SOCKET client) { sockaddr_in sa; int len = sizeof(sa); getpeername(client, (struct sockaddr*) & sa, &len); return ntohs(sa.sin_port); } void Collective_Notice(const char* text,SOCKET nosend) { for (int i = 0; i < sizeof(clientSock); i++ ) { if (clientSock[i] != nosend) { send(clientSock[i], text, MAXBYTE, 0); } } } void Collective_Notice(const char* text) { for (int i = 0; i < sizeof(clientSock); i++) { send(clientSock[i], text, MAXBYTE, 0); } } void ssend(SOCKET client, const char* text) { send(client, text, MAXBYTE, 0); } void exit() { //關閉服務 closesocket(s); WSACleanup(); }};//***************************************以上為modsocket_server********************************************
C++實例
//Server代碼// server.cpp : 此檔案包含 "main" 函式。程式執行將在此處開始並結束。//#define CRTSECURENOWARNINGS#include <iostream>#include "modsocket.h"using namespace std;//定義服務端組件modsocketserver mysocket;void error(const char* err){ cout << "error:" << err << endl;}//用戶進入void into(SOCKET client, sockaddrin info) { char* text = nullptr; text=strcat(inetntoa(info.sinaddr),"進入了聊天室>>"); mysocket.CollectiveNotice(text, client); cout << "into" << "IP:" << inetntoa(info.sinaddr)<< "PORT:" << ntohs(info.sinport) << endl; //傳送數據 send(client, "來了老弟?", sizeof("來了老弟?"), 0);}//數據到達void Received(SOCKET client, sockaddrin info, char* data) { cout << "recv:" << "IP:" << inetntoa(info.sinaddr) << "PORT:" << ntohs(info.sinport) << endl << data<<endl; //send(client, data, sizeof(data)+1, 0); char* text = nullptr; text = strcat(inetntoa(info.sinaddr), ":"); text = strcat(text, data); mysocket.CollectiveNotice(text, client);}//用戶離開void leave(SOCKET client, sockaddrin info) { char* text = nullptr; text = strcat(inetntoa(info.sinaddr), "離開了聊天室>>"); mysocket.CollectiveNotice(text, client); cout << "exit" << "IP:" << inetntoa(info.sinaddr) << "PORT:" << ntohs(info.sinport) << endl;}int main(){ mysocket.init(&into,&Received,&leave,&error,19449,true); //停止服務 mysocket.exit();}
//Client代碼#include <iostream>#include "modsocket.h"using namespace std;modbleclient client;//數據到達void Received(char* data) { cout << "recv:" << data << endl; cout << "請輸入:"; char text[MAXBYTE] = { 0 }; cin >> text; client.ssend(text);}//下線void discontinue(const char* err) { cout << "exit:"<< err << endl;}int main(){ client.init("127.0.0.1", 19449,true,&Received,&discontinue); client.exit(); return 0;}