SOCKET通訊程序源碼

最近一段時間在學習了SOCKET,下面是程序源代碼,都是在VC6.0環境下,用WIN32控制檯程序寫的:ios

1.TCP協議:服務器

先寫服務器端的程序,建立一個服務器端的工程,新創建一個C++源文件,代碼以下:數據結構

//sockServ.cpp
#include <iostream>
#include <Windows.h>
#pragma comment(lib, "WS2_32")  // 連接到WS2_32.lib 
using namespace std;

#define  PORT 4000
//#define  IP_ADDRESS "192.168.1.145"
#define  IP_ADDRESS "127.0.0.1"

DWORD WINAPI ClientThread(LPVOID lpParameter)
{
SOCKET CientSocket = (SOCKET)lpParameter;
int Ret = 0;
char RecvBuffer[MAX_PATH];
char SendBuffer[MAX_PATH];

while ( true )
{
memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
Ret = recv(CientSocket, RecvBuffer, MAX_PATH, 0);
if ( Ret == 0 || Ret == SOCKET_ERROR ) 
{
cout<<"客戶端退出!"<<endl;
break;
}
cout<<"接收到客戶信息爲:"<<RecvBuffer<<endl;
//服務器端發送信息  
cout<<"服務器端向客戶端發送以下的數據,快點在此輸入吧!:"<<endl;
cin.getline(SendBuffer, sizeof(SendBuffer));
Ret = send(CientSocket, SendBuffer, (int)strlen(SendBuffer), 0);
if ( Ret == SOCKET_ERROR )
{
cout<<"Send Info Error::"<<GetLastError()<<endl;
break;
}
}
return 0;
}

int main(int argc, char* argv[])
{
WSADATA  Ws;
SOCKET ServerSocket, CientSocket;
struct sockaddr_in LocalAddr, ClientAddr;//sockaddr_in是TCP/IP使用的數據結構
int Ret = 0;
int AddrLen = 0;
HANDLE hThread = NULL;

//Init Windows Socket
if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )//socket使用2.2版本的
{
cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
return -1;
}

//Create Socket
//第一個參數表示是INTERNET協議簇,第二個參數SOCK_STREAM表示是用TCP協議來進行通訊。第三個參數是0表示讓系統自動選擇
ServerSocket = socket(AF_INET, SOCK_STREAM, 0);
//ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( ServerSocket == INVALID_SOCKET )
{
cout<<"Create Socket Failed::"<<GetLastError()<<endl;
return -1;
}

LocalAddr.sin_family = AF_INET;//INTERNET協議簇
//LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);//這句也能夠
//LocalAddr.sin_addr.s_addr = INADDR_ANY;//這句也能夠 等同於 LocalAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
LocalAddr.sin_addr.S_un.S_addr = INADDR_ANY; 
LocalAddr.sin_port = htons(PORT);
memset(LocalAddr.sin_zero, 0x00, 8);

//Bind Socket
Ret = bind(ServerSocket, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr));
if ( Ret != 0 )
{
cout<<"Bind Socket Failed::"<<GetLastError()<<endl;
return -1;
}

Ret = listen(ServerSocket, 10);//用ServerSocket來進行監聽,監聽最多10個客戶端的請求
if ( Ret != 0 )
{
cout<<"listen Socket Failed::"<<GetLastError()<<endl;
return -1;
}

cout<<"服務端已經啓動"<<endl;
while ( true )//由於是服務器端,要不停的監聽客戶端的請求
{
AddrLen = sizeof(ClientAddr);
//用CientSocket來進行通訊
CientSocket = accept(ServerSocket, (struct sockaddr*)&ClientAddr, &AddrLen);
if ( CientSocket == INVALID_SOCKET )
{
cout<<"Accept Failed::"<<GetLastError()<<endl;
break;
}

cout<<"客戶端鏈接::"<<inet_ntoa(ClientAddr.sin_addr)<<":"<<ClientAddr.sin_port<<endl;

hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)CientSocket, 0, NULL);
if ( hThread == NULL )
{
cout<<"Create Thread Failed!"<<endl;
break;
}
CloseHandle(hThread);
}

closesocket(ServerSocket);
closesocket(CientSocket);
WSACleanup();

return 0;
}


而後再新建一個客戶端的工程,新建一個C++源文件,在其中寫入以下代碼:(注意:只能是2個工程,確定不能寫在同一個工做裏面,由於若是寫在1個工程裏面,那麼就有兩個main函數,這樣程序確定不容許的),客戶端代碼以下:socket

//sockCli.cpp
#include <iostream>
#include <Windows.h>
using namespace std;
#pragma comment(lib, "WS2_32")  // 連接到WS2_32.lib 

#define  PORT 4000
//#define  IP_ADDRESS "192.168.1.145"
#define  IP_ADDRESS "127.0.0.1"

int main(int argc, char* argv[])
{
WSADATA  Ws;
SOCKET CientSocket;
struct sockaddr_in ServerAddr;
int Ret = 0;
int AddrLen = 0;
HANDLE hThread = NULL;
char SendBuffer[MAX_PATH];
char RecvBuffer[MAX_PATH];

//Init Windows Socket
if ( WSAStartup(MAKEWORD(1,1), &Ws) != 0 )//客戶端用的SOCKET庫的版本和服務器端同樣,就算不同,也能夠正常通訊
{
cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
return -1;
}

//Create Socket
CientSocket = socket(AF_INET, SOCK_STREAM, 0);//建立了一個客戶端的SOCKET
if ( CientSocket == INVALID_SOCKET )
{
cout<<"Create Socket Failed::"<<GetLastError()<<endl;
return -1;
}

ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
ServerAddr.sin_port = htons(PORT);
memset(ServerAddr.sin_zero, 0x00, 8);
//鏈接到服務器,鏈接的服務器的地址在上面中設定
Ret = connect(CientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
if ( Ret == SOCKET_ERROR )
{
cout<<"Connect Error::"<<GetLastError()<<endl;
return -1;
}
else
{
cout<<"鏈接成功!"<<endl;
}

while ( true )
{
cout<<"你是客戶端哦,快點給服務器端說點什麼吧,好讓它知道你的存在!:"<<endl;
cin.getline(SendBuffer, sizeof(SendBuffer));
//向服務器端發送數據
Ret = send(CientSocket, SendBuffer, (int)strlen(SendBuffer), 0);
if ( Ret == SOCKET_ERROR )
{
cout<<"Send Info Error::"<<GetLastError()<<endl;
break;
}

memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
//從服務器端接收數據
Ret = recv(CientSocket, RecvBuffer, MAX_PATH, 0);
if ( Ret == 0 || Ret == SOCKET_ERROR ) 
{
cout<<"客戶端退出!"<<endl;
break;
}
cout<<"接收到服務器信息爲:"<<RecvBuffer<<endl;
}

closesocket(CientSocket);
WSACleanup();

return 0;
}


在啓動的時候,先啓動服務器端,再啓動客戶端,程序運行結果以下所示:tcp



2.UDP協議函數

下面是UDP協議的通訊:也是WIN32控制檯程序,不過啓動的時候不用像TCP同樣必需要先啓動服務器端,能夠先啓動客戶端,再啓動服務器端,能夠啓動若干個客戶端,在下面的圖中有說明,圖中就是啓動了2個客戶端,啓動了一個服務器端,注意:只能啓動一個服務器端,下面是程序源碼:學習

//sockServ.cpp
#include <iostream>
#include <Windows.h>
#pragma comment(lib, "WS2_32")  // 連接到WS2_32.lib 
using namespace std;

#define  PORT 5000
//#define  IP_ADDRESS "192.168.1.145"
#define  IP_ADDRESS "127.0.0.1"

int main(int argc, char* argv[])
{
WSADATA  Ws;
SOCKET ServerSocket, CientSocket = 0;
struct sockaddr_in LocalAddr, ClientAddr;//sockaddr_in是TCP/IP使用的數據結構
int Ret = 0;
int AddrLen = 0;
char RecvBuffer[MAX_PATH] = {0};
char SendBuffer[MAX_PATH] = {0};

//Init Windows Socket
if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )//socket使用2.2版本的
{
cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
return -1;
}

//Create Socket
//第一個參數表示是INTERNET協議簇,第二個參數SOCK_STREAM表示是用TCP協議來進行通訊。第三個參數是0表示讓系統自動選擇
ServerSocket = socket(AF_INET, SOCK_DGRAM, 0);
//ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( ServerSocket == INVALID_SOCKET )
{
cout<<"Create Socket Failed::"<<GetLastError()<<endl;
return -1;
}

LocalAddr.sin_family = AF_INET;//INTERNET協議簇
//LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
//LocalAddr.sin_addr.S_un.S_addr = INADDR_ANY;
LocalAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
LocalAddr.sin_port = htons(PORT);
memset(LocalAddr.sin_zero, 0x00, 8);

//Bind Socket
Ret = bind(ServerSocket, (sockaddr*)&LocalAddr, sizeof(LocalAddr));
if ( SOCKET_ERROR == Ret )
{
cout<<"Bind Socket Failed::"<<GetLastError()<<endl;
return -1;
}
int saddrlen = sizeof(sockaddr_in);
cout<<"服務器端啓動啦……"<<endl;


while(1)
{
memset(RecvBuffer,0,sizeof(RecvBuffer));
memset(SendBuffer,0,sizeof(SendBuffer));
Ret = recvfrom(ServerSocket,RecvBuffer,MAX_PATH,0,(sockaddr*)&ClientAddr,&saddrlen);
if(SOCKET_ERROR == Ret)
{
cout<<"服務器端接收數據錯了!"<<endl;
}
else
{
cout<<"我是服務器端,我從客戶端 "<<inet_ntoa(ClientAddr.sin_addr)<<
" 接收的數據爲:"<<RecvBuffer<<endl;
cout<<"服務器端向客戶端發送以下的數據,快點在此輸入吧!:"<<endl;
cin.getline(SendBuffer, sizeof(SendBuffer));
Ret = sendto(ServerSocket,SendBuffer,(int)strlen(SendBuffer),0,(sockaddr*)&ClientAddr,saddrlen);
if(SOCKET_ERROR == Ret)
{
cout<<"服務器端發送數據錯了!"<<endl;
}
} 
}
closesocket(ServerSocket);
closesocket(CientSocket);
WSACleanup();
return 0;
}
客戶端的程序以下:
//sockCli.cpp
#include <iostream>
#include <Windows.h>
using namespace std;
#pragma comment(lib, "WS2_32")  // 連接到WS2_32.lib 

#define  PORT 5000
//#define  IP_ADDRESS "192.168.1.145"
#define  IP_ADDRESS "127.0.0.1"

int main(int argc, char* argv[])
{
WSADATA  Ws;
SOCKET CientSocket;
struct sockaddr_in ServerAddr;
int Ret = 0;
int AddrLen = 0;
HANDLE hThread = NULL;
char SendBuffer[MAX_PATH];
char RecvBuffer[MAX_PATH];

//Init Windows Socket
if ( WSAStartup(MAKEWORD(1,1), &Ws) != 0 )//客戶端用的SOCKET庫的版本和服務器端同樣,就算不同,也能夠正常通訊
{
cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
return -1;
}

//Create Socket
CientSocket = socket(AF_INET, SOCK_DGRAM, 0);//建立了一個客戶端的SOCKET
if ( CientSocket == INVALID_SOCKET )
{
cout<<"Create Socket Failed::"<<GetLastError()<<endl;
return -1;
}

ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
ServerAddr.sin_port = htons(PORT);
memset(ServerAddr.sin_zero, 0x00, 8);
int saddrlen = sizeof(sockaddr_in);


while (1)
{
memset(RecvBuffer,0,sizeof(RecvBuffer));
memset(SendBuffer,0,sizeof(SendBuffer));
cout<<"你是客戶端哦,快點給服務器端說點什麼吧,好讓它知道你的存在!:"<<endl;
cin.getline(SendBuffer, sizeof(SendBuffer));
Ret = sendto(CientSocket,SendBuffer,(int)strlen(SendBuffer),0,(sockaddr*)&ServerAddr,saddrlen);
if(SOCKET_ERROR == Ret)
{
cout<<"客戶端發送數據錯了!"<<endl;
}
else
{
Ret = recvfrom(CientSocket,RecvBuffer,MAX_PATH,0,(sockaddr*)&ServerAddr,&saddrlen);
if(SOCKET_ERROR == Ret)
{
cout<<"客戶端接收數據錯了!"<<endl;
}
else
{
cout<<"我是客戶端,我從服務器端 "<<inet_ntoa(ServerAddr.sin_addr)<<
" 接收的數據爲:"<<RecvBuffer<<endl;
} 
}
}

closesocket(CientSocket);
WSACleanup();
return 0;
}



3.TCP用封裝的類來實現通訊:測試

服務器端:spa

#include <iostream>
#include <Windows.h>
#pragma comment(lib, "WS2_32")  // 連接到WS2_32.lib 
using namespace std;

class CTcpSrvSock
{
public:
BOOL InitSocketDll(BYTE lVer,BYTE hVer);//TCP 服務器端也有
BOOL CreateSock(int af,int type,int protocol);
BOOL InitSin(short sin_family,unsigned short sin_port,char FAR *ipAddr);
BOOL BindSin();
BOOL ListenSk(int queNum);
BOOL ConClie();//accept(ServerSocket, (struct sockaddr*)&ClientAddr, &AddrLen);
BOOL CreateCliThread();
static DWORD WINAPI ClientThread(LPVOID lpParameter);
CTcpSrvSock() {}
~CTcpSrvSock();
protected:
private:
WSADATA  Ws;
static SOCKET ServerSocket, CientSocket;
struct sockaddr_in ServerAddr, ClientAddr;//sockaddr_in是TCP/IP使用的數據結構
HANDLE hThread;
};
SOCKET CTcpSrvSock::ServerSocket = 0;
SOCKET CTcpSrvSock::CientSocket = 0;
CTcpSrvSock::~CTcpSrvSock()
{
closesocket(ServerSocket);
closesocket(CientSocket);
WSACleanup();
}
DWORD WINAPI CTcpSrvSock::ClientThread(LPVOID lpParameter)
{
char RecvBuffer[MAX_PATH];
char SendBuffer[MAX_PATH];

SOCKET CientSK = (SOCKET)lpParameter;
int Ret = 0;
while ( true )
{
memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
Ret = recv(CientSocket, RecvBuffer, MAX_PATH, 0);
if ( Ret == 0 || Ret == SOCKET_ERROR ) 
{
cout<<"客戶端退出!"<<endl;
break;
}
cout<<"接收到客戶信息爲:"<<RecvBuffer<<endl;
//服務器端發送信息  
cout<<"服務器端向客戶端發送以下的數據,快點在此輸入吧!:"<<endl;
cin.getline(SendBuffer, sizeof(SendBuffer));
Ret = send(CientSocket, SendBuffer, (int)strlen(SendBuffer), 0);
if ( Ret == SOCKET_ERROR )
{
cout<<"Send Info Error::"<<GetLastError()<<endl;
break;
}
}
return 0;
}

BOOL CTcpSrvSock::CreateCliThread()
{
hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)CientSocket, 0, NULL);
if ( hThread == NULL )
{
cout<<"Create Thread Failed!"<<endl;
return FALSE;
}
CloseHandle(hThread);
return TRUE;
}

BOOL CTcpSrvSock::ConClie()
{
struct sockaddr_in ClientAddr;//sockaddr_in是TCP/IP使用的數據結構
int AddrLen = sizeof(ClientAddr);
CientSocket = accept(ServerSocket, (struct sockaddr*)&ClientAddr, &AddrLen);
if ( CientSocket == INVALID_SOCKET )
{
cout<<"ConClie Failed::"<<GetLastError()<<endl;
return FALSE;
}
cout<<"客戶端鏈接::"<<inet_ntoa(ClientAddr.sin_addr)<<":"<<ClientAddr.sin_port<<endl;
return TRUE;
}
BOOL CTcpSrvSock::ListenSk(int queNum)
{
//用ServerSocket來進行監聽,監聽最多10個客戶端的請求
if ( listen(ServerSocket, queNum) != 0 )
{
cout<<"listen Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
cout<<"服務端已經啓動,客戶端能夠過來鏈接了"<<endl;
return TRUE;
}
BOOL CTcpSrvSock::BindSin()
{
//以下爲綁定套接字地址
if(0 != bind(ServerSocket, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr)))
{
cout<<"Bind Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
int saddrlen = sizeof(sockaddr_in);
cout<<"服務器端啓動啦……"<<endl;
return TRUE;
}
//在客戶端,初始化的是服務器端的地址
BOOL CTcpSrvSock::InitSin(short sin_family,unsigned short sin_port,char FAR *ipAddr)
{
//ipAddr爲...表示的IP地址
ServerAddr.sin_family = sin_family;//AF_INET;//INTERNET協議簇
ServerAddr.sin_addr.s_addr = inet_addr(ipAddr);//s_addr--unsigned long
//skInRet.sin_addr.S_un.S_addr = //INADDR_ANY; 
//skInRet.sin_addr.s_addr = inet_addr(IP_ADDRESS);//這句也能夠
//skInRet.sin_addr.s_addr = INADDR_ANY;
//等同於 skInRet.sin_addr.s_addr = inet_addr("0.0.0.0");
//skInRet.sin_addr.S_un.S_addr = INADDR_ANY; 
ServerAddr.sin_port = htons(sin_port);
memset(ServerAddr.sin_zero, 0x00, 8);
return TRUE;
}

BOOL CTcpSrvSock::CreateSock(int af,int type,int protocol)
{
ServerSocket = socket(af, type, protocol);
//ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( ServerSocket == INVALID_SOCKET )
{
cout<<"Create Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
return TRUE;
}
BOOL CTcpSrvSock::InitSocketDll(BYTE lVer,BYTE hVer)//初始化SOCKET庫
{
if ( WSAStartup(MAKEWORD(lVer,hVer), &Ws) != 0 )//socket使用2.2版本的
{
cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
return TRUE;
}

class CUdpSrvSock
{
public:
BOOL InitSocketDll(BYTE lVer,BYTE hVer);//TCP 服務器端也有
BOOL CreateSock(int af,int type,int protocol);
BOOL InitSin(short sin_family,unsigned short sin_port,char FAR *ipAddr);
BOOL BindSin();
SOCKET GetCliSocket(){return CientSocket;}
SOCKET GetSrvSocket(){return ServerSocket;}
sockaddr_in GetSrvAdr(){return ServerAddr;}
// sockaddr_in GetCliAdr(){return ClientAddr;}
CUdpSrvSock() {}
~CUdpSrvSock();
protected:
private:
WSADATA  Ws;
static SOCKET ServerSocket, CientSocket;
struct sockaddr_in ServerAddr, ClientAddr;//sockaddr_in是TCP/IP使用的數據結構
HANDLE hThread;

};
SOCKET CUdpSrvSock::ServerSocket = 0;
SOCKET CUdpSrvSock::CientSocket = 0;
CUdpSrvSock::~CUdpSrvSock()
{
closesocket(ServerSocket);
closesocket(CientSocket);
WSACleanup();
}

BOOL CUdpSrvSock::BindSin()
{
//以下爲綁定套接字地址
if(0 != bind(ServerSocket, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr)))
{
cout<<"Bind Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
return TRUE;
}
//在客戶端,初始化的是服務器端的地址
BOOL CUdpSrvSock::InitSin(short sin_family,unsigned short sin_port,char FAR *ipAddr)
{
//ipAddr爲...表示的IP地址
ServerAddr.sin_family = sin_family;//AF_INET;//INTERNET協議簇
ServerAddr.sin_addr.s_addr = inet_addr(ipAddr);//s_addr--unsigned long
//skInRet.sin_addr.S_un.S_addr = //INADDR_ANY; 
//skInRet.sin_addr.s_addr = inet_addr(IP_ADDRESS);//這句也能夠
//skInRet.sin_addr.s_addr = INADDR_ANY;
//等同於 skInRet.sin_addr.s_addr = inet_addr("0.0.0.0");
//skInRet.sin_addr.S_un.S_addr = INADDR_ANY; 
ServerAddr.sin_port = htons(sin_port);
memset(ServerAddr.sin_zero, 0x00, 8);
return TRUE;
}

BOOL CUdpSrvSock::CreateSock(int af,int type,int protocol)
{
ServerSocket = socket(af, type, protocol);
//ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( ServerSocket == INVALID_SOCKET )
{
cout<<"Create Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
return TRUE;
}
BOOL CUdpSrvSock::InitSocketDll(BYTE lVer,BYTE hVer)//初始化SOCKET庫
{
if ( WSAStartup(MAKEWORD(lVer,hVer), &Ws) != 0 )//socket使用2.2版本的
{
cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
return TRUE;
}
int TestTCPSerCode()
{
cout<<"TCP服務器端已經啓動"<<endl;
CTcpSrvSock tcpSrv1;
tcpSrv1.InitSocketDll(2,2);
tcpSrv1.CreateSock(AF_INET,SOCK_STREAM,0);
tcpSrv1.InitSin(AF_INET,6000,"0.0.0.0");
tcpSrv1.BindSin();
tcpSrv1.ListenSk(5);
while(1)
{
tcpSrv1.ConClie();
tcpSrv1.CreateCliThread();
}
return 0;
}
int TestUDPSerCode()
{
CUdpSrvSock udpsrv;
udpsrv.InitSocketDll(2,2);
udpsrv.CreateSock(AF_INET,SOCK_DGRAM,0);
udpsrv.InitSin(AF_INET,5000,"0.0.0.0");
udpsrv.BindSin();


char SendBuffer[MAX_PATH];
char RecvBuffer[MAX_PATH];
int saddrlen = sizeof(sockaddr_in);
sockaddr_in ClientAddr;
cout<<"UDP服務器端已經啓動"<<endl;
while(1)
{
memset(RecvBuffer,0,sizeof(RecvBuffer));
memset(SendBuffer,0,sizeof(SendBuffer));
int Ret = recvfrom(udpsrv.GetSrvSocket(),RecvBuffer,MAX_PATH,0,
(sockaddr*)&ClientAddr,&saddrlen);
if(SOCKET_ERROR == Ret)
{
cout<<"服務器端接收數據錯了!"<<endl;
}
else
{
cout<<"我是服務器端,我從客戶端 "<<inet_ntoa(ClientAddr.sin_addr)<<
" 接收的數據爲:"<<RecvBuffer<<endl;
cout<<"服務器端向客戶端發送以下的數據,快點在此輸入吧!:"<<endl;
cin.getline(SendBuffer, sizeof(SendBuffer));
Ret = sendto(udpsrv.GetSrvSocket(),SendBuffer,(int)strlen(SendBuffer),0,(sockaddr*)&ClientAddr,saddrlen);
if(SOCKET_ERROR == Ret)
{
cout<<"服務器端發送數據錯了!"<<endl;
}
} 
}
return 0;
}

int main()
{
TestTCPSerCode();
//TestUDPSerCode();
return 0;
//UD
}



客戶端:
code

#include <iostream>
#include <Windows.h>
#pragma comment(lib, "WS2_32")  // 連接到WS2_32.lib 
using namespace std;

class CTcpCliSock
{
public:
BOOL InitSocketDll(BYTE lVer,BYTE hVer);//use
BOOL CreateSock(int af,int type,int protocol);//user
BOOL InitSin(short sin_family,unsigned short sin_port,char FAR *ipAddr);//use
//BOOL BindSin();
//BOOL ListenSk(int queNum);
BOOL ConClie();//use
BOOL CreateCliThread();//use
static DWORD WINAPI ClientThread(LPVOID lpParameter);
CTcpCliSock(){}
~CTcpCliSock();
SOCKET GetCliSocket(){return CientSocket;}//new
protected:
private:
WSADATA  Ws;
static SOCKET ServerSocket, CientSocket;
struct sockaddr_in ServerAddr, ClientAddr;//sockaddr_in是TCP/IP使用的數據結構
HANDLE hThread;
char RecvBuffer[MAX_PATH];
char SendBuffer[MAX_PATH];
};
SOCKET CTcpCliSock::ServerSocket = 0;
SOCKET CTcpCliSock::CientSocket = 0;

CTcpCliSock::~CTcpCliSock()
{
closesocket(ServerSocket);
closesocket(CientSocket);
WSACleanup();
}

DWORD WINAPI CTcpCliSock::ClientThread(LPVOID lpParameter)
{
char RecvBuffer[MAX_PATH];
char SendBuffer[MAX_PATH];

cout<<"你是客戶端哦,快點給服務器端說點什麼吧,好讓它知道你的存在!:"<<endl;
cin.getline(SendBuffer, sizeof(SendBuffer));
//向服務器端發送數據
if ( send(CientSocket, SendBuffer, (int)strlen(SendBuffer), 0) == SOCKET_ERROR )
{
cout<<"Send Info Error::"<<GetLastError()<<endl;
}
else
{
memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
//從服務器端接收數據
int Ret = recv(CientSocket, RecvBuffer, MAX_PATH, 0);
if ( Ret == 0 || Ret == SOCKET_ERROR ) 
{
cout<<"客戶端退出!"<<endl;
}
else 
{
cout<<"從服務器接收到的信息爲:"<<RecvBuffer<<endl;
}
}
return 0;
}

BOOL CTcpCliSock::CreateCliThread()
{
hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)CientSocket, 0, NULL);
if ( hThread == NULL )
{
cout<<"Create Thread Failed!"<<endl;
return FALSE;
}
CloseHandle(hThread);
return TRUE;
}
//在服務器端是用此來聯接客戶端,在客戶端是要鏈接客戶端
BOOL CTcpCliSock::ConClie()
{
if ( connect(CientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR )
{
cout<<"Connect Error::"<<GetLastError()<<endl;
return FALSE;
}
cout<<"服務器端鏈接客戶端成功!"<<endl;
return TRUE;
}

BOOL CTcpCliSock::InitSin(short sin_family,unsigned short sin_port,char FAR *ipAddr)
{
//ipAddr爲...表示的IP地址
ServerAddr.sin_family = sin_family;//AF_INET;//INTERNET協議簇
ServerAddr.sin_addr.s_addr = inet_addr(ipAddr);//s_addr--unsigned long
//skInRet.sin_addr.S_un.S_addr = //INADDR_ANY; 
//skInRet.sin_addr.s_addr = inet_addr(IP_ADDRESS);//這句也能夠
//skInRet.sin_addr.s_addr = INADDR_ANY;//等同於 skInRet.sin_addr.s_addr = inet_addr("0.0.0.0");
//skInRet.sin_addr.S_un.S_addr = INADDR_ANY; 
ServerAddr.sin_port = htons(sin_port);
memset(ServerAddr.sin_zero, 0x00, 8);
return TRUE;
}

BOOL CTcpCliSock::CreateSock(int af,int type,int protocol)
{
CientSocket  = socket(af, type, protocol);
//ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( CientSocket == INVALID_SOCKET )
{
cout<<"Create Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
return TRUE;
}
BOOL CTcpCliSock::InitSocketDll(BYTE lVer,BYTE hVer)//初始化SOCKET庫
{
if ( WSAStartup(MAKEWORD(lVer,hVer), &Ws) != 0 )//socket使用2.2版本的
{
cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
return TRUE;
}

class CUdpCliSock
{
public:
BOOL InitSocketDll(BYTE lVer,BYTE hVer);//use
BOOL CreateSock(int af,int type,int protocol);//user
BOOL InitSin(short sin_family,unsigned short sin_port,char FAR *ipAddr);//use
CUdpCliSock(){}
sockaddr_in GetSrvAddr(){return ServerAddr;}
~CUdpCliSock();
SOCKET GetCliSocket(){return CientSocket;}//new
protected:
private:
WSADATA  Ws;
static SOCKET ServerSocket, CientSocket;
struct sockaddr_in ServerAddr, ClientAddr;//sockaddr_in是TCP/IP使用的數據結構
HANDLE hThread;
char RecvBuffer[MAX_PATH];
char SendBuffer[MAX_PATH];
};
SOCKET CUdpCliSock::ServerSocket = 0;
SOCKET CUdpCliSock::CientSocket = 0;

CUdpCliSock::~CUdpCliSock()
{
closesocket(ServerSocket);
closesocket(CientSocket);
WSACleanup();
}

BOOL CUdpCliSock::InitSin(short sin_family,unsigned short sin_port,char FAR *ipAddr)
{
//ipAddr爲...表示的IP地址
ServerAddr.sin_family = sin_family;//AF_INET;//INTERNET協議簇
ServerAddr.sin_addr.s_addr = inet_addr(ipAddr);//s_addr--unsigned long
//skInRet.sin_addr.S_un.S_addr = //INADDR_ANY; 
//skInRet.sin_addr.s_addr = inet_addr(IP_ADDRESS);//這句也能夠
//skInRet.sin_addr.s_addr = INADDR_ANY;//等同於 skInRet.sin_addr.s_addr = inet_addr("0.0.0.0");
//skInRet.sin_addr.S_un.S_addr = INADDR_ANY; 
ServerAddr.sin_port = htons(sin_port);
memset(ServerAddr.sin_zero, 0x00, 8);
return TRUE;
}

BOOL CUdpCliSock::CreateSock(int af,int type,int protocol)
{
CientSocket  = socket(af, type, protocol);
//ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( CientSocket == INVALID_SOCKET )
{
cout<<"Create Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
return TRUE;
}
BOOL CUdpCliSock::InitSocketDll(BYTE lVer,BYTE hVer)//初始化SOCKET庫
{
if ( WSAStartup(MAKEWORD(lVer,hVer), &Ws) != 0 )//socket使用2.2版本的
{
cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
return FALSE;
}
return TRUE;
}

int TestTCPCliCode()
{
CTcpCliSock tcpCli1;
tcpCli1.InitSocketDll(2,2);
tcpCli1.CreateSock(AF_INET,SOCK_STREAM,0);
tcpCli1.InitSin(AF_INET,6000,"127.0.0.1");
tcpCli1.ConClie();
while(1)
{
char SendBuffer[MAX_PATH];
char RecvBuffer[MAX_PATH];
//tcpCli1.CreateCliThread();
cout<<"我是客戶端哦,我正在用TCP和服務器端通訊,快點給服務器端說點什麼吧,好讓它知道你的存在!:"<<endl;
cin.getline(SendBuffer, sizeof(SendBuffer));
//向服務器端發送數據
int Ret = send(tcpCli1.GetCliSocket(), SendBuffer, (int)strlen(SendBuffer), 0);
if ( Ret == SOCKET_ERROR )
{
cout<<"Send Info Error::"<<GetLastError()<<endl;
}

memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
//從服務器端接收數據
Ret = recv(tcpCli1.GetCliSocket(), RecvBuffer, MAX_PATH, 0);
if ( Ret == 0 || Ret == SOCKET_ERROR ) 
{
cout<<"客戶端退出!"<<endl;
}
cout<<"接收到服務器信息爲:"<<RecvBuffer<<endl;
}
return 0;
}

int TestUDPCliCode()
{
CUdpCliSock udpclisk;
udpclisk.InitSocketDll(2,2);
udpclisk.CreateSock(AF_INET,SOCK_DGRAM,0);
udpclisk.InitSin(AF_INET,5000,"127.0.0.1");
char SendBuffer[MAX_PATH];
char RecvBuffer[MAX_PATH];
int saddrlen = sizeof(sockaddr_in);
sockaddr_in myServerAddr;

while (1)
{
memset(RecvBuffer,0,sizeof(RecvBuffer));
memset(SendBuffer,0,sizeof(SendBuffer));
cout<<"我是客戶端哦,我正在用UDP和服務器端通訊,快點給服務器端說點什麼吧,好讓它知道你的存在!:"<<endl;
cin.getline(SendBuffer, sizeof(SendBuffer));
int Ret = sendto(udpclisk.GetCliSocket(),SendBuffer,(int)strlen(SendBuffer),
0,(sockaddr*)&(udpclisk.GetSrvAddr()),saddrlen);
if(SOCKET_ERROR == Ret)
{
cout<<"客戶端發送數據錯了!"<<endl;
break;
}

Ret = recvfrom(udpclisk.GetCliSocket(),RecvBuffer,MAX_PATH,0,
(sockaddr*)&myServerAddr,&saddrlen);
if(SOCKET_ERROR == Ret)
{
cout<<"客戶端接收數據錯了!"<<endl;
}
else
{
cout<<"我是客戶端,我從服務器端 "<<inet_ntoa(myServerAddr.sin_addr)<<
" 接收的數據爲:"<<RecvBuffer<<endl;
} 
}
return 0;
}
int main()
{
TestTCPCliCode();
//TestUDPCliCode();
return 0;
}


測試結果以下圖所示:

以下圖爲TCP通訊效果圖:

以下圖爲UDP通訊效果圖:

相關文章
相關標籤/搜索