ソースコード (ここをコピペすべし!)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#ifdef WIN32
#include <WinSock2.h>
#include <Windows.h>
#include <process.h>
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#endif
#ifdef WIN32
#define HERROR WSAGetLastError()
#define SAFE_SOCK_CLOSE(sock) if((sock) != INVALID_SOCKET){ closesocket((sock)); (sock)=INVALID_SOCKET; }
#define SOCK_TYPE SOCKET
#define SOCKLEN_TYPE int
#define SLEEP_SEC(sec) Sleep((sec) * 1000)
#define SET_SOCKADDR_IPV4(addr, value) (addr).sin_addr.S_un.S_addr = (value)
#else
#define HERROR h_errno
#define INVALID_SOCKET (-1)
#define SAFE_SOCK_CLOSE(sock) if((sock) != INVALID_SOCKET){ close((sock)); (sock)=INVALID_SOCKET; }
#define SOCK_TYPE int
#define SOCKLEN_TYPE socklen_t
#define SLEEP_SEC(sec) sleep((sec))
#define SET_SOCKADDR_IPV4(addr, value) (addr).sin_addr.s_addr = (value)
#endif
#define SAFE_DELETE(p) if(p){ delete(p); (p)=NULL; }
const char* errno_str()
{
switch (errno)
{
case 1: return "EPERM";
case 2: return "ENOENT";
case 3: return "ESRCH";
case 4: return "EINTR";
case 5: return "EIO";
case 6: return "ENXIO";
case 7: return "E2BIG";
case 8: return "ENOEXEC";
case 9: return "EBADF";
case 10: return "ECHILD";
case 11: return "EAGAIN or EWOULDBLOCK";
case 12: return "ENOMEM";
case 13: return "EACCES";
case 14: return "EFAULT";
case 15: return "ENOTBLK";
case 16: return "EBUSY";
case 17: return "EEXIST";
case 18: return "EXDEV";
case 19: return "ENODEV";
case 20: return "ENOTDIR";
case 21: return "EISDIR";
case 22: return "EINVAL";
case 23: return "ENFILE";
case 24: return "EMFILE";
case 25: return "ENOTTY";
case 26: return "ETXTBSY";
case 27: return "EFBIG";
case 28: return "ENOSPC";
case 29: return "ESPIPE";
case 30: return "EROFS";
case 31: return "EMLINK";
case 32: return "EPIPE";
case 33: return "EDOM";
case 34: return "ERANGE";
case 35: return "EDEADLK or EDEADLOCK";
case 36: return "ENAMETOOLONG";
case 37: return "ENOLCK";
case 38: return "ENOSYS";
case 39: return "ENOTEMPTY";
case 40: return "ELOOP";
case 42: return "ENOMSG";
case 43: return "EIDRM";
case 44: return "ECHRNG";
case 45: return "EL2NSYNC";
case 46: return "EL3HLT";
case 47: return "EL3RST";
case 49: return "EUNATCH";
case 51: return "EL2HLT";
case 52: return "EBADE";
case 53: return "EBADR";
case 54: return "EXFULL";
case 56: return "EBADRQC";
case 57: return "EBADSLT";
case 60: return "ENOSTR";
case 61: return "ENODATA";
case 62: return "ETIME";
case 63: return "ENOSR";
case 64: return "ENONET";
case 65: return "ENOPKG";
case 66: return "EREMOTE";
case 67: return "ENOLINK";
case 70: return "ECOMM";
case 71: return "EPROTO";
case 72: return "EMULTIHOP";
case 74: return "EBADMSG";
case 75: return "EOVERFLOW";
case 76: return "ENOTUNIQ";
case 77: return "EBADFD";
case 78: return "EREMCHG";
case 79: return "ELIBACC";
case 80: return "ELIBBAD";
case 81: return "ELIBSCN";
case 82: return "ELIBMAX";
case 83: return "ELIBEXEC";
case 84: return "EILSEQ";
case 85: return "ERESTART";
case 86: return "ESTRPIPE";
case 87: return "EUSERS";
case 88: return "ENOTSOCK";
case 89: return "EDESTADDRREQ";
case 90: return "EMSGSIZE";
case 91: return "EPROTOTYPE";
case 92: return "ENOPROTOOPT";
case 93: return "EPROTONOSUPPORT";
case 94: return "ESOCKTNOSUPPORT";
case 95: return "ENOTSUP or EOPNOTSUPP";
case 96: return "EPFNOSUPPORT";
case 97: return "EAFNOSUPPORT";
case 98: return "EADDRINUSE";
case 99: return "EADDRNOTAVAIL";
case 100: return "ENETDOWN";
case 101: return "ENETUNREACH";
case 102: return "ENETRESET";
case 103: return "ECONNABORTED";
case 104: return "ECONNRESET";
case 105: return "ENOBUFS";
case 106: return "EISCONN";
case 107: return "ENOTCONN";
case 108: return "ESHUTDOWN";
case 110: return "ETIMEDOUT";
case 111: return "ECONNREFUSED";
case 112: return "EHOSTDOWN";
case 113: return "EHOSTUNREACH";
case 114: return "EALREADY";
case 115: return "EINPROGRESS";
case 116: return "ESTALE";
case 117: return "EUCLEAN";
case 120: return "EISNAM";
case 121: return "EREMOTEIO";
case 122: return "EDQUOT";
case 123: return "ENOMEDIUM";
case 124: return "EMEDIUMTYPE";
case 125: return "ECANCELED";
case 126: return "ENOKEY";
case 127: return "EKEYEXPIRED";
case 128: return "EKEYREVOKED";
case 129: return "EKEYREJECTED";
default: return "UNKNOWN";
}
}
const char* getLocalTimeStr(time_t curTime, char* pszResultTime)
{
struct tm* pt = localtime(&curTime);
sprintf(pszResultTime, "%02d/%02d/%02d %02d:%02d:%02d", pt->tm_year + 1900, pt->tm_mon + 1, pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec);
return pszResultTime;
}
class NetworkInfo
{
public:
~NetworkInfo()
{
#ifdef WIN32
if (bWSASetup)
{
WSACleanup();
bWSASetup = false;
}
#endif
SAFE_SOCK_CLOSE(sock0);
}
#ifdef WIN32
WSADATA wsaData;
bool bWSASetup;
#endif
SOCK_TYPE sock0;
struct sockaddr_in addr;
struct sockaddr_in client_addr_forsend;
NetworkInfo() :
#ifdef WIN32
wsaData(),
bWSASetup(false),
#endif
sock0(INVALID_SOCKET),
addr(),
client_addr_forsend()
{
}
};
enum NodeType
{
eNodeTypeUnknown = 0,
eServer,
eClient
};
static const char* NODE_SERVER = "server";
static const char* NODE_CLIENT = "client";
enum ProtocolType
{
eProtocolTypeUnknown = 0,
eProtocolTCP,
eProtocolUDP
};
static const char* PROTOCOL_TCP = "tcp";
static const char* PROTOCOL_UDP = "udp";
struct RecvInfo_t
{
SOCK_TYPE recvSock_;
RecvInfo_t(SOCK_TYPE recvSock) :
recvSock_(recvSock)
{
}
};
#ifdef WIN32
unsigned __stdcall recvThread(void *p)
#else
void* recvThread(void *p)
#endif
{
RecvInfo_t* pRecvInfo = (RecvInfo_t *)p;
char inbuf[2048];
char atimeWk[64];
memset(inbuf, 0, sizeof(inbuf));
memset(atimeWk, 0, sizeof(atimeWk));
SOCK_TYPE sock = pRecvInfo->recvSock_;
SAFE_DELETE(pRecvInfo);
recv(sock, inbuf, sizeof(inbuf), 0);
printf("%s Received Message:%s\n", getLocalTimeStr(time(NULL), atimeWk), inbuf);
SAFE_SOCK_CLOSE(sock);
#ifdef WIN32
return 0;
#else
pthread_exit(NULL);
#endif
}
void printUsage()
{
printf("Usage:\n");
printf(" server {tcp|udp} listening_addr listening_port\n");
printf(" or\n");
printf(" client {tcp|udp} dest_addr dest_port src_addr src_port message\n");
printf("\n");
printf("Example:\n");
printf(" 1. server tcp 192.168.1.5 12345\n");
printf(" client tcp 192.168.1.5 12345 0 0 sample_to_12345\n");
printf("\n");
printf(" 2. server udp 192.168.1.5 12345\n");
printf(" client udp 192.168.1.5 12345 192.168.1.2 5000 sample_from_5000_to_12345\n");
}
int main(int argc, char* argv[])
{
if (argc <= 1)
{
fprintf(stderr, "Error: Bad args num.\n");
printUsage();
return 1;
}
NodeType eNodeType = eNodeTypeUnknown;
if (strcmp(argv[1], NODE_SERVER) == 0)
{
eNodeType = eServer;
if (argc != 5)
{
fprintf(stderr, "Error: Bad args num(Server)(%d).\n", argc);
printUsage();
return 1;
}
}
else if (strcmp(argv[1], NODE_CLIENT) == 0)
{
eNodeType = eClient;
if (argc != 8)
{
fprintf(stderr, "Error: Bad args num(Client)(%d).\n", argc);
printUsage();
return 1;
}
}
else
{
fprintf(stderr, "Error: Input correct NodeType(server or client).\n");
printUsage();
return 2;
}
ProtocolType eProtocolType = eProtocolTypeUnknown;
if (strcmp(argv[2], PROTOCOL_TCP) == 0)
{
eProtocolType = eProtocolTCP;
}
else if (strcmp(argv[2], PROTOCOL_UDP) == 0)
{
eProtocolType = eProtocolUDP;
}
else
{
fprintf(stderr, "Error: Input correct ProtocolType(tcp or udp).\n");
printUsage();
return 2;
}
int nFuncRet = 0;
NetworkInfo netInfo;
char atimeWk[64];
memset(atimeWk, 0, sizeof(atimeWk));
#ifdef WIN32
nFuncRet = WSAStartup(MAKEWORD(2, 0), &(netInfo.wsaData));
netInfo.bWSASetup = true;
if (nFuncRet != 0)
{
fprintf(stderr, "%s WSAStartup error(%d)(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), nFuncRet, HERROR, errno, errno_str());
return 3;
}
#endif
if (eNodeType == eServer)
{
const char* pszAddr = argv[3];
const char* pszPortNum = argv[4];
netInfo.sock0 = socket(AF_INET, (eProtocolType == eProtocolTCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
if (netInfo.sock0 == INVALID_SOCKET)
{
fprintf(stderr, "%s listen socket error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str());
return 4;
}
netInfo.addr.sin_family = AF_INET;
netInfo.addr.sin_port = htons(atoi(pszPortNum)); TODO
SET_SOCKADDR_IPV4(netInfo.addr, inet_addr(pszAddr)); TODO
{
int nYes = 1;
setsockopt(netInfo.sock0, SOL_SOCKET, SO_REUSEADDR, (const char *)&nYes, sizeof(nYes));
}
nFuncRet = bind(netInfo.sock0, (struct sockaddr *)&(netInfo.addr), sizeof(netInfo.addr));
if (nFuncRet == -1)
{
fprintf(stderr, "%s bind(recv) error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str());
return 8;
}
if (eProtocolType == eProtocolTCP)
{
nFuncRet = listen(netInfo.sock0, 5);
if (nFuncRet == -1)
{
fprintf(stderr, "%s listen error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str());
return 9;
}
}
while (1)
{
struct sockaddr_in client = { 0 };
SOCKLEN_TYPE nClientLen = sizeof(client);
if (eProtocolType == eProtocolTCP)
{
int sock = INVALID_SOCKET;
sock = accept(netInfo.sock0, (struct sockaddr *)&client, &nClientLen);
if (sock == INVALID_SOCKET)
{
fprintf(stderr, "%s accept error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str());
continue;
}
RecvInfo_t* pRecvInfo = NULL;
try
{
pRecvInfo = new RecvInfo_t(sock);
}
catch (...)
{
SAFE_SOCK_CLOSE(sock);
continue;
}
#ifdef WIN32
unsigned int thID = 0;
HANDLE hThread = (HANDLE)_beginthreadex(NULL,
0,
recvThread,
pRecvInfo,
0 ,
&thID);
if (hThread == 0)
{
fprintf(stderr, "%s _beginthreadex error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str());
SAFE_SOCK_CLOSE(sock);
continue;
}
#else
pthread_t th = 0;
nFuncRet = pthread_create(&th, NULL, recvThread, (void *)pRecvInfo);
if (nFuncRet != 0)
{
fprintf(stderr, "%s pthread_create error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str());
SAFE_SOCK_CLOSE(sock);
continue;
}
(void)pthread_detach(th);
#endif
}
else
{
char inbuf[2048];
char atimeWk[64];
memset(inbuf, 0, sizeof(inbuf));
memset(atimeWk, 0, sizeof(atimeWk));
recv(netInfo.sock0, inbuf, sizeof(inbuf), 0);
printf("%s Received Message:%s\n", getLocalTimeStr(time(NULL), atimeWk), inbuf);
}
}
}
else
{
const char* pszDestAddr = argv[3];
const char* pszDestPortNum = argv[4];
const char* pszSrcAddr = argv[5];
const char* pszSrcPortNum = argv[6];
const char* pszMessage = argv[7];
int sock = 0;
char sendmsg[256];
memset(sendmsg, 0, sizeof(sendmsg));
netInfo.addr.sin_family = AF_INET;
netInfo.addr.sin_port = htons(atoi(pszDestPortNum)); TODO
SET_SOCKADDR_IPV4(netInfo.addr, inet_addr(pszDestAddr)); TODO
netInfo.client_addr_forsend.sin_family = AF_INET;
netInfo.client_addr_forsend.sin_port = htons(atoi(pszSrcPortNum)); TODO
SET_SOCKADDR_IPV4(netInfo.client_addr_forsend, inet_addr(pszSrcAddr)); TODO
sock = socket(AF_INET, (eProtocolType == eProtocolTCP) ? SOCK_STREAM : SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
{
fprintf(stderr, "%s socket(send) h_errno:%d errno:%d(%s)\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str());
return 10;
}
TODO
{
int nYes = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&nYes, sizeof(nYes));
}
TODO
nFuncRet = bind(sock, (struct sockaddr *)&(netInfo.client_addr_forsend), sizeof(netInfo.client_addr_forsend));
if (nFuncRet == -1)
{
fprintf(stderr, "%s bind(send) error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str());
return 11;
}
memset(sendmsg, 0, sizeof(sendmsg));
strncpy(sendmsg, pszMessage, sizeof(sendmsg) - 1);
if (eProtocolType == eProtocolTCP)
{
nFuncRet = connect(sock, (struct sockaddr *)&(netInfo.addr), sizeof(netInfo.addr));
if (nFuncRet == -1)
{
fprintf(stderr, "%s connect error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str());
return 12;
}
(void)send(sock, sendmsg, (int)strlen(sendmsg), 0);
}
else
{
(void)sendto(sock, sendmsg, (int)strlen(sendmsg), 0, (struct sockaddr *)&netInfo.addr, sizeof(netInfo.addr));
}
SAFE_SOCK_CLOSE(sock);
}
return 0;
}