最近一段时间在学习了SOCKET,下面是程序源代码,都是在VC6.0环境下,用WIN32控制台程序写的:
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函数,这样程序肯定不允许的),客户端代码如下:
//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;
}
在启动的时候,先启动服务器端,再启动客户端,程序运行结果如下所示:
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用封装的类来实现通信:
服务器端:
#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
}
客户端:
#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通信效果图: