sockserver.cpp
#include <stdio.h>
//#include <winsock.h>
#include <msgpack.hpp>
#include <vector>
#include <string>
#include <iostream>
// Function prototype
void StreamServer3(short nPort);
// Helper macro for displaying errors
#define PRINTERROR(s) \
fprintf(stderr,"\n%: %d\n", s, WSAGetLastError())
////////////////////////////////////////////////////////////
void main(int argc, char **argv)
{
WORD wVersionRequested = MAKEWORD(1,1);
WSADATA wsaData;
int nRet;
short nPort;
//
// Check for port argument
//
if (argc != 2)
{
fprintf(stderr,"\nSyntax: server PortNumber\n");
return;
}
nPort = atoi(argv[1]);
//
// Initialize WinSock and check version
//
nRet = WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested)
{
fprintf(stderr,"\n Wrong version\n");
return;
}
//
// Do the stuff a stream server does
//
StreamServer3(nPort);
//
// Release WinSock
//
WSACleanup();
}
class MSGREQ_020
{
private:
public:
int iSeq;
std::string strSvcType;
int iReqMax;
MSGREQ_020():iSeq(0),strSvcType(""),iReqMax(0){}
MSGREQ_020(const int s,const std::string & st, const int max):iSeq(s),strSvcType(st),iReqMax(max){}
MSGPACK_DEFINE(iSeq , strSvcType , iReqMax);
};
class MSGRSP_021
{
private:
public:
int iSeq;
std::vector<std::string> vecServers;
MSGRSP_021():iSeq(0){}
MSGRSP_021(const int s):iSeq(s){}
MSGPACK_DEFINE(iSeq ,vecServers);
};
void StreamServer3(short nPort)
{
//
// Create a TCP/IP stream socket to "listen" with
//
SOCKET listenSocket;
listenSocket = socket(AF_INET, // Address family
SOCK_STREAM, // Socket type
IPPROTO_TCP); // Protocol
if (listenSocket == INVALID_SOCKET)
{
PRINTERROR("socket()");
return;
}
//
// Fill in the address structure
//
SOCKADDR_IN saServer;
saServer.sin_family = AF_INET;
saServer.sin_addr.s_addr = INADDR_ANY; // Let WinSock supply address
saServer.sin_port = htons(nPort); // Use port from command line
//
// bind the name to the socket
//
int nRet;
nRet = bind(listenSocket, // Socket
(LPSOCKADDR)&saServer, // Our address
sizeof(struct sockaddr));// Size of address structure
if (nRet == SOCKET_ERROR)
{
PRINTERROR("bind()");
closesocket(listenSocket);
return;
}
//
// This isn't normally done or required, but in this
// example we're printing out where the server is waiting
// so that you can connect the example client.
//
int nLen;
nLen = sizeof(SOCKADDR);
char szBuf[4096];
nRet = gethostname(szBuf, sizeof(szBuf));
if (nRet == SOCKET_ERROR)
{
PRINTERROR("gethostname()");
closesocket(listenSocket);
return;
}
//
// Show the server name and port number
//
printf("\nServer named %s waiting on port %d\n",
szBuf, nPort);
//
// Set the socket to listen
//
printf("\nlisten()");
nRet = listen(listenSocket, // Bound socket
SOMAXCONN); // Number of connection request queue
if (nRet == SOCKET_ERROR)
{
PRINTERROR("listen()");
closesocket(listenSocket);
return;
}
//
// Wait for an incoming request
//
SOCKET remoteSocket;
printf("\nBlocking at accept()\n\n");
remoteSocket = accept(listenSocket, // Listening socket
NULL, // Optional client address
NULL);
if (remoteSocket == INVALID_SOCKET)
{
PRINTERROR("accept()\n\n");
closesocket(listenSocket);
return;
}
//
// We're connected to a client
// New socket descriptor returned already
// has clients address
//
// Receive data from the client
//
memset(szBuf, 0, sizeof(szBuf));
nRet = recv(remoteSocket, // Connected client
szBuf, // Receive buffer
sizeof(szBuf), // Length of buffer
0); // Flags
if (nRet == INVALID_SOCKET)
{
PRINTERROR("recv()");
closesocket(listenSocket);
closesocket(remoteSocket);
return;
}
// feeds the buffer.
char *pszContent = &szBuf[3];
int nContentLen = nRet-5;
msgpack::unpacked msg;
msgpack::unpack(&msg, pszContent, nContentLen);
msgpack::object obj = msg.get();
msgpack::object_kv* pkv;
msgpack::object_kv* pkv_end;
msgpack::object pk, pv;
MSGREQ_020 msg_020;
//
// Display received data
//
if(obj.via.map.size > 0)
{
pkv = obj.via.map.ptr;
pkv_end = obj.via.map.ptr + obj.via.map.size;
std::string key;
pkv->key.convert (&key);
pkv->val.convert (&msg_020);
}
//
// Send data back to the client
//
char szBuf2[4096];
MSGRSP_021 msg_021;
unsigned short *len = (unsigned short *)&szBuf2[1];
szBuf2[0]=0x02;
msg_021.iSeq = msg_020.iSeq;
msg_021.vecServers.push_back("fdt00.com.tw");
msgpack::sbuffer sbuf;
msgpack::packer<msgpack::sbuffer> pker(&sbuf);
pker.pack_map(1);
pker.pack(std::string("021"));
pker.pack(msg_021);
memcpy(&szBuf2[3],sbuf.data(), sbuf.size());
*len=sbuf.size();
szBuf2[3+ sbuf.size()]=0;
for(int jj = 0 ; jj < (sbuf.size()+3) ; jj++)
{
if(jj > 2)
szBuf2[3+ sbuf.size()] ^= szBuf2[jj];
}
szBuf2[3+sbuf.size()+1]=0x03;
nRet = send(remoteSocket, // Connected socket
szBuf2, // Data buffer
sbuf.size()+5, // Length of data
0); // Flags
//
// Close BOTH sockets before exiting
//
closesocket(remoteSocket);
closesocket(listenSocket);
return;
}
sockclient.cpp
//msgpack not allow data aliment as pack(1), use default VC++ data aliment , pack(8)
//#pragma pack(push) /* push current alignment to stack */
//#pragma pack(8) /* set alignment to 1 byte boundary */
#include <stdio.h>
//#include <winsock.h>
#include <msgpack.hpp>
#include <vector>
#include <string>
#include <iostream>
//#pragma pack(pop) /* restore original alignment from stack */
// Function prototype
void StreamClient3(char *szServer, short nPort);
// Helper macro for displaying errors
#define PRINTERROR(s) \
fprintf(stderr,"\n%: %d\n", s, WSAGetLastError())
////////////////////////////////////////////////////////////
void main(int argc, char **argv)
{
WORD wVersionRequested = MAKEWORD(1,1);
WSADATA wsaData;
int nRet;
short nPort;
//
// Check for the host and port arguments
//
if (argc != 3)
{
fprintf(stderr,"\nSyntax: client ServerName PortNumber\n");
return;
}
nPort = atoi(argv[2]);
//
// Initialize WinSock and check the version
//
nRet = WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested)
{
fprintf(stderr,"\n Wrong version\n");
return;
}
//
// Go do the stuff a stream client does
//
StreamClient3(argv[1], nPort);
//
// Release WinSock
//
WSACleanup();
}
class MSGREQ_020
{
private:
public:
int iSeq;
std::string strSvcType;
int iReqMax;
MSGREQ_020():iSeq(0),strSvcType(""),iReqMax(0){}
MSGREQ_020(const int s,const std::string & st, const int max):iSeq(s),strSvcType(st),iReqMax(max){}
MSGPACK_DEFINE(iSeq , strSvcType , iReqMax);
};
class MSGRSP_021
{
private:
public:
int iSeq;
std::vector<std::string> vecServers;
MSGRSP_021():iSeq(0){}
MSGRSP_021(const int s):iSeq(s){}
MSGPACK_DEFINE(iSeq ,vecServers);
};
////////////////////////////////////////////////////////////
void StreamClient3(char *szServer, short nPort)
{
printf("\nStream Client connecting to server: %s on port: %d\n\n",
szServer, nPort);
//
// Find the server
//
LPHOSTENT lpHostEntry;
lpHostEntry = gethostbyname(szServer);
if (lpHostEntry == NULL)
{
PRINTERROR("gethostbyname()");
return;
}
//
// Create a TCP/IP stream socket
//
SOCKET theSocket;
theSocket = socket(AF_INET,// Address family
SOCK_STREAM,// Socket type
IPPROTO_TCP); // Protocol
if (theSocket == INVALID_SOCKET)
{
PRINTERROR("socket()");
return;
}
//
// Fill in the address structure
//
SOCKADDR_IN saServer;
saServer.sin_family = AF_INET;
// Server's address
saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
saServer.sin_port = htons(nPort); // Port number from command line
//
// connect to the server
//
int nRet;
nRet = connect(theSocket, // Socket
(LPSOCKADDR)&saServer, // Server address
sizeof(struct sockaddr));// Length of server address structure
if (nRet == SOCKET_ERROR)
{
PRINTERROR("socket()");
closesocket(theSocket);
return;
}
/******************************************************
<0x02><length>[MessagePacket Content]<bccChecksum><0x03>
-----------------------
Serialization
Serializtion: pker.pack_map(1);
pker.pack(std::string("020")); //key
pker.pack(msg_020); //your own class
******************************************************/
char szBuf2[4096];
MSGREQ_020 msg_020;
unsigned short *len = (unsigned short *)&szBuf2[1];
szBuf2[0]=0x02;
msg_020.iSeq = 2345;
msg_020.strSvcType = "sean";
msg_020.iReqMax=0;
msgpack::sbuffer sbuf;
msgpack::packer<msgpack::sbuffer> pker(&sbuf);
pker.pack_map(1);
pker.pack(std::string("020"));
pker.pack(msg_020);
memcpy(&szBuf2[3],sbuf.data(), sbuf.size());
*len=sbuf.size(); // length only for sbuf.data()
szBuf2[3+ sbuf.size()]=0;
// checksum only sbuf.data()
for(int jj = 0 ; jj < (sbuf.size()+3) ; jj++)
{
if(jj > 2)
szBuf2[3+ sbuf.size()] ^= szBuf2[jj];
}
szBuf2[3+sbuf.size()+1]=0x03;
nRet = send(theSocket,// Connected socket
szBuf2, // Data buffer
sbuf.size()+5, // Length of data, head(3),tail(2,checksum+tail)
0); // Flags
/*******************************************************/
/*******************************************************/
if (nRet == SOCKET_ERROR)
{
PRINTERROR("send()");
closesocket(theSocket);
return;
}
//
// Wait for a reply
//
char szBuf[4096];
nRet = recv(theSocket, // Connected socket
szBuf, // Receive buffer
sizeof(szBuf), // Size of receive buffer
0); // Flags
if (nRet == SOCKET_ERROR)
{
PRINTERROR("recv()");
closesocket(theSocket);
return;
}
char *pszContent = &szBuf[3];
int nContentLen = nRet-5;
msgpack::unpacked msg;
msgpack::unpack(&msg, pszContent, nContentLen);
msgpack::object obj = msg.get();
msgpack::object_kv* pkv;
msgpack::object_kv* pkv_end;
msgpack::object pk, pv;
MSGRSP_021 msg_021;
if(obj.via.map.size > 0)
{
pkv = obj.via.map.ptr;
pkv_end = obj.via.map.ptr + obj.via.map.size;
std::string key;
pkv->key.convert (&key);
pkv->val.convert (&msg_021);
for(int kk=0 ; kk < msg_021.vecServers.size(); ++kk)
{
if(kk==0)
std::cout << key << "-->" << msg_021.iSeq << "," << msg_021.vecServers[kk] << std::endl;
else
std::cout <<" --> ," << msg_021.vecServers[kk] << std::endl;
}
}
//
// Display the received data
//
closesocket(theSocket);
system("PAUSE");
return;
}
執行結果:
Stream Client connecting to server: 127.0.0.1 on port: 5000
021-->2345,fdt00.com.tw
請按任意鍵繼續 . . .