最近一段时间在学习了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通信效果图: