- Server
#include <WinSock2.h>
#include <windows.h>
#include <iostream>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
using namespace std;
Pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib"
int main(a)
{
WORD version = MAKEWORD(2.2);
WSADATA data;
WSAStartup(version, &data);
// Create socket
SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind the listening network port
sockaddr_in _sin = {};
_sin.sin_family = AF_INET;
_sin.sin_port = htons(4567);
_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int ret = bind(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in));
if (SOCKET_ERROR == ret)
{
cout << "Failed to bind port" << endl;
return - 1;
}
cout << "Bond port successfully" << endl;
if (SOCKET_ERROR == listen(_sock, 5))
{
cout << "Listening failed." << endl;
return - 1;
}
cout << "Listening successful." << endl;
// Waiting to receive a client connection
sockaddr_in client_addr = {};
int nRecvLen = sizeof(sockaddr_in);
SOCKET _client = INVALID_SOCKET;
char buf[] = "hello,client";
cout << strlen(buf) << endl;
while (true)
{
_client = accept(_sock, (sockaddr *)&client_addr, &nRecvLen);
if (_client == INVALID_SOCKET)
{
cout << "Invalid SOCKET" << endl;
}
// Get the client address
cout << "New client added, IP:" << inet_ntoa(client_addr.sin_addr) << endl;
send(_client, buf, strlen(buf) + 1.0); // Add the terminator
}
/ / close the socket
closesocket(_sock);
WSACleanup(a);return 0;
}
Copy the code
- client
#include <WinSock2.h>
#include <windows.h>
#include <iostream>
//#define _WINSOCK_DEPRECATED_NO_WARNINGS
using namespace std;
Pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib"
int main(a)
{
WORD version = MAKEWORD(2.2);
WSADATA data;
WSAStartup(version, &data);
SOCKET _sock = socket(AF_INET,SOCK_STREAM,0);
if (SOCKET_ERROR == _sock)
{
cout << "Bond port successfully" << endl;
return - 1;
}
sockaddr_in _sin = {}; // Address of the server to be connected
_sin.sin_family = AF_INET;
_sin.sin_port = htons(4567);
_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (SOCKET_ERROR == connect(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in)))
{
cout << "Connection failed" << endl;
return - 1;
}
cout << "Server connection successful" << endl;
while (true)
{
char cmdBuf[1024] = {};
scanf("%s", cmdBuf);
if (0= =strcmp(cmdBuf, "exit"))
{
break;
}
else
{
send(_sock, cmdBuf, strlen(cmdBuf)+1 ,0);
}
char recv_buf[1024] = {};
int nLen = recv(_sock, recv_buf, 1024.0);
cout << "nLen = " << nLen << endl;
if (nLen > 0)
{
cout << "Received data:"<< recv_buf << endl; }}/ / close the socket
closesocket(_sock);
WSACleanup(a);return 0;
}
Copy the code
Structure strong binary stream
struct Data{
int code;
char name[256];
}
Data data = {1."wang"};
send(socket,(const char *)&data,strlen(data)+1.0);
Copy the code
When there are multiple services, the server receives the data and has no way of knowing which structure object to force the binary stream into. In network communication, a packet usually contains a packet header and a packet body. We can construct a structure whose packet header describes the packet body.
eg:
emun CMD
{
CMD_LOGIN,
CMD_LOGIN_RESULT,
CMD_LOGOUT,
CMD_LOGOUT_RESULT,
ERROR
}
struct DataHeader
{
int dataLength;
int cmd;
}
struct Login : public DataHeader
{
Login()
{
dataLength = sizeof(Login);
cmd = CMD_LOGIN;
}
char username[32];
char password[32];
}
Copy the code
The server reads recV data in two times. The first time the request header is read, the second time the header information is read the request body of the specified length. Make a simple change to the above code:
- server
#include <WinSock2.h>
#include <windows.h>
#include <iostream>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
using namespace std;
Pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib"
enum CMD
{
CMD_LOGIN,
CMD_LOGIN_RESULT,
CMD_LOGOUT,
CMD_LOGOUT_RESULT,
CMD_ERROR
};
struct DataHeader
{
int dataLength;
int cmd;
};
struct Login : public DataHeader
{
Login()
{
dataLength = sizeof(Login);
cmd = CMD_LOGIN;
}
char username[32];
char password[32];
};
struct LoginResult : public DataHeader
{
LoginResult()
{
dataLength = sizeof(LoginResult);
cmd = CMD_LOGIN_RESULT;
result = 0;
}
int result;
};
struct Logout : public DataHeader
{
Logout()
{
dataLength = sizeof(Logout);
cmd = CMD_LOGOUT;
}
char username[32];
};
struct LogoutResult : public DataHeader
{
LogoutResult()
{
dataLength = sizeof(LogoutResult);
cmd = CMD_LOGOUT;
result = 0;
}
int result;
};
int main(a)
{
WORD version = MAKEWORD(2.2);
WSADATA data;
WSAStartup(version, &data);
// Create socket
SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind the listening network port
sockaddr_in _sin = {};
_sin.sin_family = AF_INET;
_sin.sin_port = htons(4567);
_sin.sin_addr.S_un.S_addr = ADDR_ANY;
if (SOCKET_ERROR == bind(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in)))
{
cout << "Failed to bind port" << endl;
return - 1;
}
cout << "Bond port successfully" << endl;
if (SOCKET_ERROR == listen(_sock, 5))
{
cout << "Listening failed." << endl;
return - 1;
}
cout << "Listening successful." << endl;
// Waiting to receive a client connection
sockaddr_in client_addr = {};
int nRecvLen = sizeof(sockaddr_in);
cout << "nRecvLen = " << nRecvLen << endl;
SOCKET _client = - 1;
char recvBuf[1024] = {};
_client = accept(_sock, (sockaddr *)&client_addr, &nRecvLen);
if (_client == INVALID_SOCKET)
{
cout << "Invalid SOCKET" << endl;
}
// Get the client address
cout << "New client added, IP:" << inet_ntoa(client_addr.sin_addr) << endl;
while (true)
{
// Use a buF to receive the data in the request header first
char szRecv[1024] = {};
int nLen = recv(_client, (char*)&szRecv, sizeof(DataHeader),0);
DataHeader* header = (DataHeader*)szRecv;
if (nLen <= 0)
{
cout << "Client has exited." << endl;
break;
}
// cout << "received command" << recvBuf << endl;
switch (header->cmd)
{
case CMD_LOGIN:
{
recv(_client, szRecv +sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
Login* login = (Login*)szRecv;
cout << "Received data: CMD_LOGIN, length:" << login->dataLength << ",username:" << login->username << ",password" << login->password << endl;
LoginResult loginRes = {};
send(_client,(const char*)&loginRes,sizeof(loginRes),0);
break;
}
case CMD_LOGOUT:
{
recv(_client, szRecv +sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
Logout* logout = (Logout*)szRecv;
cout << "Received data: CMD_LOGOUT, length:" << logout->dataLength << ",username:" << logout->username << endl;
LogoutResult logoutRes = {};
send(_client, (const char*)&logoutRes, sizeof(logoutRes), 0);
break;
}
default:
DataHeader header = { 0,CMD_ERROR };
/*header->cmd = CMD_ERROR; header->dataLength = 0; * /
send(_client, (const char*)&header, sizeof(header), 0);
break; }}/ / close the socket
closesocket(_sock);
WSACleanup(a);return 0;
}
Copy the code
- client
#include <WinSock2.h>
#include <windows.h>
#include <iostream>
//#define _WINSOCK_DEPRECATED_NO_WARNINGS
using namespace std;
Pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib"
enum CMD
{
CMD_LOGIN,
CMD_LOGIN_RESULT,
CMD_LOGOUT,
CMD_LOGOUT_RESULT,
CMD_ERROR
};
struct DataHeader
{
int dataLength;
int cmd;
};
struct Login : public DataHeader
{
Login()
{
dataLength = sizeof(Login);
cmd = CMD_LOGIN;
}
char username[32];
char password[32];
};
struct LoginResult : public DataHeader
{
LoginResult()
{
dataLength = sizeof(LoginResult);
cmd = CMD_LOGIN_RESULT;
result = 0;
}
int result;
};
struct Logout : public DataHeader
{
Logout()
{
dataLength = sizeof(Logout);
cmd = CMD_LOGOUT;
}
char username[32];
};
struct LogoutResult : public DataHeader
{
LogoutResult()
{
dataLength = sizeof(LogoutResult);
cmd = CMD_LOGOUT;
result = 0;
}
int result;
};
int main(a)
{
WORD version = MAKEWORD(2.2);
WSADATA data;
WSAStartup(version, &data);
SOCKET _sock = socket(AF_INET,SOCK_STREAM,0);
if (SOCKET_ERROR == _sock)
{
cout << "Bond port successfully" << endl;
return - 1;
}
sockaddr_in _sin = {}; // Address of the server to be connected
_sin.sin_family = AF_INET;
_sin.sin_port = htons(4567);
_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (SOCKET_ERROR == connect(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in)))
{
cout << "Connection failed" << endl;
return - 1;
}
cout << "Server connection successful" << endl;
while (true)
{
char cmdBuf[1024] = {};
scanf("%s", cmdBuf);
if (0= =strcmp(cmdBuf, "login"))
{
Login login;
strcpy(login.username,"scott");
strcpy(login.password,"123456");
send(_sock, (const char*)&login, sizeof(login), 0);
// Receive the return value
LoginResult loginRes = {};
recv(_sock,(char*)&loginRes,sizeof(loginRes),0);
cout << "Return value:" << loginRes.result << endl;
}
else if (0= =strcmp(cmdBuf, "logout"))
{
Logout logout = {};
strcpy(logout.username, "scott");
send(_sock, (const char*)&logout, sizeof(logout), 0);
// Receive the return value
LogoutResult logoutRes = {};
recv(_sock, (char*)&logoutRes, sizeof(logoutRes), 0);
cout << "Return value:" << logoutRes.result << endl;
}
else if (0= =strcmp(cmdBuf, "exit"))
{
cout << "Stop connection" << endl;
break;
}
else
{
cout << "Input error instruction" << endl;
break; }}/ / close the socket
closesocket(_sock);
WSACleanup(a);return 0;
}
Copy the code
The Base version is all that, but blocking singlet, which is definitely not possible in real development, and we need a way to send and receive messages that doesn’t block all the time.