最近一段時間在學習了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通訊效果圖: