用一個類實現網絡通訊功能:

TCP/IP 通訊

背景或原因: 經常要使用網絡通訊,爲了方便,編寫一個類,使之能像流一樣工作。

環境:windows系統、可執行c++程序、網絡連接正常

具體功能:完成TCP/IP 通訊。其中TCP服務端、TCP客戶端、UDP方式可選,以類似流的方式及使用">>"、"<<"來接收和發送且傳輸量可選。

使用示例:

#include "nstream.h"
int main()
{
nstream tcps(8000);//選擇tcp 服務端 端口:8000
char c[6] = "hello";
while(1)
{
tcps<<c;//發送6個字符
tcps>>c;//接收6個字符
}
return 0;
}

頭文件 “nstream.h ”

#include <Windows.h>
#pragma comment(lib, "ws2_32.lib")
class nstream
{
public:
nstream(const int TcpLocPort4Ser);
nstream(const char* TcpRemIpAdd4Cli, const int TcpSerPor4Cli);
nstream(const int UdpLocPort,const char* UdpRemIpAdd, const int UdpRemPort);
~nstream();
int getn();
private: 
bool Init();
bool CreateSocket(int type, int protocol);

bool BindSock();
bool Listen(const int n);
bool Accept();

bool Connect();

//其中T不能使指針類型(數組頭指針可以)
template<typename T> friend nstream& operator << (nstream& os, const T &Struct)
{
SOCKADDR_IN sockadd = os.StruAdd; //必須賦值
if(os.TraType)//UDP
{
os.num = sendto(os.Sock,(const char*)&Struct,sizeof(Struct), 0,(const sockaddr *)&sockadd, sizeof(SOCKADDR));
}
else if((os.num = send(os.Sock,(const char*)&Struct,sizeof(Struct), 0)) == SOCKET_ERROR)
{
cout<<"Send Info Error::"<<GetLastError()<<endl;
throw("");
}
return os;
}
//其中T不能使指針類型(數組頭指針可以)
template<typename T> friend nstream& operator >> (nstream& in, const T &Struct)
{
int len = sizeof(SOCKADDR);
SOCKADDR_IN sockadd;// = in.StruAdd; 必須不賦值
if(in.TraType)//UDP
{
in.num =recvfrom(in.Sock, (char*)&Struct, sizeof(Struct), 0,(SOCKADDR*)&sockadd,&len);
}
else if((in.num = (in.Sock, (char*)&Struct, sizeof(Struct), 0)) == 0 || in.num == SOCKET_ERROR)
{
cout<<"Recv Info Error::"<<GetLastError()<<endl;
throw("");
}
return in;
} 
private:
WSADATA  Ws; //版本號
bool TraType; //false->TCP, true->UDP
SOCKET Sock; //工作
SOCKET ServerSock;//僅TCPS使用
struct sockaddr_in StruAdd;
int num;//傳輸的字符數或狀態
};

源文件"nstream.cpp":

<pre name="code" class="cpp">#include "nstream.h"
#include <iostream>
using namespace std;
//TCP_SERVER
nstream::nstream(const int TcpLocPort4Ser)
:TraType(false)
, num(0)
{
Init();
StruAdd.sin_addr.s_addr = inet_addr("127.0.0.1");// 32位IP地址  htonl (INADDR_ANY) === inet_addr("127.0.0.1")
StruAdd.sin_port = htons(TcpLocPort4Ser);// 16位端口號

CreateSocket(SOCK_STREAM, IPPROTO_TCP);

BindSock();

Listen(10);
Accept();
}
//TCP_CLIENT
nstream::nstream(const char* TcpRemIpAdd4Cli, const int TcpSerPor4Cli)
:TraType(false)
, num(0)
{ 
Init();
StruAdd.sin_addr.s_addr = inet_addr(TcpRemIpAdd4Cli);
StruAdd.sin_port = htons(TcpSerPor4Cli);

CreateSocket(SOCK_STREAM, IPPROTO_TCP);

Connect();
}
//UDP_SERVER && CLIENT
nstream::nstream(const int UdpLocPort,const char* UdpRemIpAdd, const int UdpRemPort)
:TraType(true)
, num(0)
{
Init();
StruAdd.sin_addr.s_addr = inet_addr("127.0.0.1");
StruAdd.sin_port = htons(UdpLocPort);

CreateSocket(SOCK_DGRAM, 0);

BindSock();

StruAdd.sin_addr.s_addr = inet_addr(UdpRemIpAdd);
StruAdd.sin_port = htons(UdpRemPort);
}
//析構
nstream::~nstream()
{
}
//獲得傳輸返回值
int nstream::getn()
{
<span style="white-space:pre">	</span>return num;
}
//初始化
bool nstream::Init()
{
if (WSAStartup(MAKEWORD(2,2), &Ws))
{
cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
throw("");
return false; 
}
if(LOBYTE(Ws.wVersion)!=2 || HIBYTE(Ws.wHighVersion)!=2){
WSACleanup();
cout<<"Init Windows Socket Failed"<<endl;
throw("");
return false;
}
StruAdd.sin_family = AF_INET;// 協議族,必須是AF_INET 
memset(StruAdd.sin_zero, 0x00, 8);
return true;
}


//創建套接字
bool nstream::CreateSocket(int type, int protocol)
{
Sock = ServerSock = socket(AF_INET, type, protocol);
if ( Sock == INVALID_SOCKET ) { 
cout<<"Create Socket Failed::"<<GetLastError()<<endl;
throw("");
return false;
}
return true;
}

//tcps 綁定
bool nstream::BindSock()
{ 
if(bind(ServerSock, (struct sockaddr*)&StruAdd, sizeof(sockaddr)) != 0)
{ 
cout<<"Bind Socket Failed::"<<GetLastError()<<endl;
throw("");
return false; 
}
return true;
}
//tcps 監聽
bool nstream::Listen(const int n)
{
if (listen(ServerSock, n) != 0)
{ 
cout<<"listen Socket Failed::"<<GetLastError()<<endl; 
throw("");
return false;
}
return false;
}
//tcps 接受連接請求
bool nstream::Accept()
{
int AddrLen = sizeof(StruAdd);
Sock = accept(ServerSock, (struct sockaddr*)&StruAdd, &AddrLen);//-------
if (Sock == INVALID_SOCKET )
{ 
cout<<"Accept Failed::"<<GetLastError()<<endl;
throw("");
return false; 
}
return true;
}

//tcpC 請求連接
bool nstream::Connect()
{
if(connect(Sock,(struct sockaddr*)&StruAdd, sizeof(StruAdd)) == SOCKET_ERROR )
{ 
cout<<"Connect Error::"<<GetLastError()<<endl;
throw("");
return false; 
}
return true;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章