[C++] Windows 下 Socket 局域網通信實用模板

2018.9.24

PracticalSocket.hpp


//2018.9.24
#include<cstdio>
#include<windows.h>
#pragma comment(lib, "ws2_32.lib")  

int ContractHost(const char* sendData,char* recData,int recLen,const char* HostIp, int portnum){ //給服務器發送信息 
	
    WORD sockVersion = MAKEWORD(2, 2);//一些初始的東西 
    WSADATA data;
    if(WSAStartup(sockVersion, &data)!=0)return -2;//創建失敗 
    
    SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sclient == INVALID_SOCKET)return -1;//創建失敗
	
    sockaddr_in serAddr;//嘗試與主機建立連接 
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(portnum);
    serAddr.sin_addr.S_un.S_addr = inet_addr(HostIp);//主機
	
    if(connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)  
    { 
        closesocket(sclient);
        return -3;//連接失敗,一般爲主機不存在
        #define HOST_NOT_EXIST (-3)
    }
	
    send(sclient, sendData, strlen(sendData), 0);
    int ret = recv(sclient, recData, recLen, 0);  
    recData[ret] = 0x00;//set EOS
    closesocket(sclient);
    
    WSACleanup();//最後的一些處理 
    return 0;//通信成功
    #define CONTRACT_SUC (0)
}

class ServerSocket{//服務端被以類的形式定義 
    WORD sockVersion;    
    WSADATA wsaData;
    SOCKET slisten;
    sockaddr_in sin;
    SOCKET sClient;
    sockaddr_in remoteAddr;
    int nAddrlen;   
    
    public:
    int InitServer(const char* ipname, int portnum){ //啓動  // ipname = 本機IP地址
        sockVersion = MAKEWORD(2,2);
        if(WSAStartup(sockVersion, &wsaData)!=0)
            return -1;//fail
		
        slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    
        if(slisten == INVALID_SOCKET)    
            return -2;//socket error  
	   
        sin.sin_family = AF_INET;//綁定IP和端口  
        sin.sin_port = htons(portnum);
        sin.sin_addr.S_un.S_addr = inet_addr(ipname);
        if(bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)    
            return -3;//bind error
	    
        if(listen(slisten, 5) == SOCKET_ERROR)//開始監聽 
            return -4;//listen error
		    
        nAddrlen = sizeof(remoteAddr);//準備循環接收數據 
        return 0;//suc
    }
    const char* WaitMessage(char* revData,int recLen){
        sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);//等待連接
        if(sClient == INVALID_SOCKET) return (const char *)NULL;//accept error
        //inet_ntoa(remoteAddr.sin_addr) 接受到的地址的字符串 
        int ret = recv(sClient, revData, recLen, 0);
        revData[ret] = 0x00;//set EOS
        return inet_ntoa(remoteAddr.sin_addr);
    }
    void Feedback(const char* sendData){//反饋一段信息 
        send(sClient, sendData, strlen(sendData), 0);    
        closesocket(sClient);
    }
    void DestructHost(){//結束一個服務器 
        closesocket(slisten);    
    	WSACleanup();    
    }
};

Server.cpp


#include"PracticalSocket.hpp"
#include<iostream>
ServerSocket ss;
#define DataLen (255)
#include<sstream>
#include<string>
using namespace std;
char recData[DataLen];
int react(){
	stringstream path;
	if(recData[0] == '$') {
		printf("[Server] send system operation ... ");
		int ret = system(&recData[1]); /// 直接傳遞指令
		printf(" [OK]\n"); 
		return ret;
	}
	path<<recData; string label; path>>label; /// input front label
	if(label == "exit") return -0x7fffffff; //exit
	if(label == "cursor"){
		printf("[Server] cursor set... ");
		int x,y; path>>x>>y; SetCursorPos(x,y);
		printf(" [OK]\n");
	}else if(label == "keyboard"){
		printf("[Server] keyboard ... ");
		//int ascii = 0; path>>ascii; /// input ascii
		int ascii = 0;
		while((path>>ascii) && ascii) {
            keybd_event(ascii,0,0,0);
		    keybd_event(ascii,0,KEYEVENTF_KEYUP,0);
		    ascii = 0;
        }
		printf(" [OK]\n");
	}else if(label == "beep"){
		int fqc = 0, tim = 0;
		while((path>>fqc>>tim) && tim) {
            if(fqc > 0) Beep(fqc, tim);
            else Sleep(tim);
		    tim = 0;
        }
	}else if(label == "hide"){
         
    }else {
          
    }
}
int main(){
	char HostIp[18] = {};
	cout<<"[Server] input host ip: "; cin>>HostIp; /// 輸入本機IP 
	cout<<"[Server] InitServer... "; ss.InitServer(HostIp, 8888); cout<<" [OK]"<<endl;
	while(1){
		//clear(recData);
		recData[0] = 0; cout<<"[Server] WaitMessage ... ";
		ss.WaitMessage(recData,DataLen); cout<<" [OK]"<<endl;
		if(recData[0]) { /// 過濾空白信息 
			int t = react(); if(t == -0x7fffffff) break;
			cout<<"[Server] Message: "<<recData<<" "<<endl;
			ss.Feedback("[Server] Message Get Successfully!");
		}
		cout<<endl;
	}
	cout<<"[Server] DestructHost... "; ss.DestructHost(); cout<<" [OK]"<<endl;
	return 0;
}

Client.cpp


#include"PracticalSocket.hpp"
#include<iostream>
#define cin  std::cin
#define cout std::cout
#define cerr std:cerr
#define endl std::endl
//#define endl std::endl
#define DataLen (255)
#include<cstring>
#define clear(A) memset(A,0,sizeof(A))
char recData[DataLen],msg[DataLen];
int main(){
	cout<<"[Client] input HostIp: ";
	char HostIp[18] = {}; cin>>HostIp;
	while(1){
		clear(recData);
		clear(msg);
		cout<<"[Client] InputMessage: ";
		gets(msg);//input message
		if(msg[0]==0)continue;
		cout<<"[Client] ContractHost... ";
		int t=ContractHost(msg,recData,DataLen,HostIp, 8888); /// 填入正確的IP地址 
		cout<<" [OK] return with "<< t <<endl;
		cout<<"Message: "<<recData<<endl<<endl;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章