ModSocket

ModSocket

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;}

相關詞條

熱門詞條

聯絡我們