最基本的Winsock的程序。
本来应该作为博客的代码Wiki部分进行保存,而不是一篇博文的。无奈自建博客的计划迟迟没有开动的迹象,先忍忍。
这两个文件完成了最简单的Winsock的例子:服务器端进行侦听,客户端发起连接,发送数据,服务器端收到数据后进行反馈。
下面是客户端的代码文件:
// ClientProcess.cpp #include "StdAfx.h" #include "ClientProcess.h" #include <iostream> #include <WinSock2.h> #pragma comment(lib, "Wsock32") using namespace std; #define CHECK_SOCK_ERROR(funName, cond) \ do { \ if (cond) \ { \ cout<<#funName" error: "<<WSAGetLastError()<<endl; \ return; \ } \ }while(0) void PrepairWinsock(){ WSADATA wsaData; WORD sockVersion = MAKEWORD(2, 0); if (0 != WSAStartup(sockVersion, &wsaData)) { cout<<"WSAStartup Error!"<<endl; } } void CleanWinsock(){ WSACleanup(); } void SentData(){ SOCKET clientSocket = NULL; // type 0 is TCP/IP clientSocket = socket(AF_INET, SOCK_STREAM, 0); int serverPort = 4444; SOCKADDR_IN serverSockAddr; serverSockAddr.sin_family = AF_INET; serverSockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 服务器端是同一主机 serverSockAddr.sin_port = htons(serverPort); // 端口为1024到5000之间的任意值 int ret = connect(clientSocket, (LPSOCKADDR)&serverSockAddr, sizeof(serverSockAddr)); CHECK_SOCK_ERROR(connect, ret); char strSend[] = "test data!"; ret = send(clientSocket, strSend, sizeof(strSend), 0); CHECK_SOCK_ERROR(send, SOCKET_ERROR == ret); int const BUFF_SIZE = 256; char buff[BUFF_SIZE] = {0}; cout<<"Start recv"<<endl; ret = recv(clientSocket, buff, BUFF_SIZE, 0); CHECK_SOCK_ERROR(recv, SOCKET_ERROR == ret); cout<<"Recv Data: "<<buff<<endl; closesocket(clientSocket); } void SendDataByWinSock(){ PrepairWinsock(); SentData(); CleanWinsock(); }
另一个是服务器端的代码:
//ServerProcess.cpp #include "StdAfx.h" #include "ServerProcess.h" #include <iostream> #include <string> #include <WinSock2.h> #pragma comment(lib, "Wsock32") using namespace std; #define CHECK_SOCK_ERROR(funName, cond) \ do { \ if (cond) \ { \ cout<<#funName" error: "<<WSAGetLastError()<<endl; \ return; \ } \ }while(0) void PrepairWinsock(){ WSADATA wsaData; WORD sockVersion = MAKEWORD(2, 0); if (0 != WSAStartup(sockVersion, &wsaData)) { cout<<"WSAStartup Error!"<<endl; } } void CleanWinsock(){ WSACleanup(); } void WaitForData(){ SOCKET serverSocket = NULL; // type 0 is TCP/IP serverSocket = socket(AF_INET, SOCK_STREAM, 0); int serverPort = 4444; SOCKADDR_IN serverSockAddr; serverSockAddr.sin_family = AF_INET; serverSockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); serverSockAddr.sin_port = htons(serverPort); // 端口为1024到5000之间的任意值 cout<<"Start bind"<<endl; int ret = bind(serverSocket, (LPSOCKADDR)&serverSockAddr, sizeof(serverSockAddr)); CHECK_SOCK_ERROR(bind, SOCKET_ERROR == ret); cout<<"Start listen"<<endl; ret = listen(serverSocket, 2); CHECK_SOCK_ERROR(listen, SOCKET_ERROR == ret); cout<<"Start accept"<<endl; // accept 会返回另一个socket,这个socket用于通信,而原来的 // sockte继续进行侦听。 SOCKET dataCommuSock = accept(serverSocket, NULL, NULL); CHECK_SOCK_ERROR(accept, INVALID_SOCKET == dataCommuSock); int const BUFF_SIZE = 256; char buff[BUFF_SIZE] = {0}; cout<<"Start recv"<<endl; ret = recv(dataCommuSock, buff, BUFF_SIZE, 0); CHECK_SOCK_ERROR(recv, (0 == ret) || (SOCKET_ERROR == ret)); string strRecv(buff); cout<<"recv message : "<<strRecv<<endl; strRecv += strRecv; send(dataCommuSock, strRecv.c_str(), strRecv.size(), 0); CHECK_SOCK_ERROR(send, SOCKET_ERROR == ret); cout<<"close socket"<<endl; closesocket(serverSocket); closesocket(dataCommuSock); } void GetDataByWinSock(){ PrepairWinsock(); WaitForData(); CleanWinsock(); }
这里面的对socket的调用都是阻塞式的。