I'm now facing the problem of C++ winsock server programming for receiving messages from both TCP and UDP. In fact, UDP is used for receiving the job message from another server, while TCP receives messages from multiple RFID receivers.
So I've googled for days to see what approach I can use, and I found the followings:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms738620(v=vs.85).aspx http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch08lev1sec15.html
However, I still cannot come up with the clear flow that how I can start the server application without selecting either TCP or UDP by the command line arguement i.e. I just want to start the winsock server program with creating both TCP and UDP sockets and then wait for connections.
So, according to the above two links, how can I do for the purpose I stated above i.e. how can I initialize the TCP and UDP sockets when I start the program and then go into the while loop for waiting the connections? Thanks!
Edited 20150918 4:12pm HKT
I've tried to combine the examples in two links provided above, but it is work for TCP while not in UDP. What is the problem for UDP according to the following server and client codes? Thanks!
server.cpp
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define STRICMP _stricmp
#define DEFAULT_PORT 5001
#define DEFAULT_PROTO SOCK_STREAM // TCP
void Usage(char *progname) {
fprintf(stderr, "Usage\n%s -e [endpoint] -i [interface]\n",
progname);
fprintf(stderr, "Where:\n\tendpoint is the port to listen on\n");
fprintf(stderr, "\tinterface is the ipaddr (in dotted decimal notation)");
fprintf(stderr, " to bind to\n");
fprintf(stderr, "Defaults are 5001 and INADDR_ANY\n");
WSACleanup();
exit(1);
}
int main(int argc, char **argv) {
char Buffer[128];
char *interface = NULL;
unsigned short port = DEFAULT_PORT;
int retval;
int fromlen;
int i;
int maxfdp1, nready;
struct sockaddr_in local, from;
WSADATA wsaData;
SOCKET listen_socket, udp_socket, msgsock;
fd_set SockSet;
/* Parse arguments */
if (argc >1) {
for (i = 1; i <argc; i++) {
if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
switch (tolower(argv[i][1])) {
case 'i':
interface = argv[++i];
break;
case 'e':
port = (unsigned short)atoi(argv[++i]);
break;
default:
Usage(argv[0]);
break;
}
}
else
Usage(argv[0]);
}
}
if ((retval = WSAStartup(0x202, &wsaData)) != 0) {
fprintf(stderr, "WSAStartup failed with error %d\n", retval);
WSACleanup();
return -1;
}
if (port == 0){
Usage(argv[0]);
}
local.sin_family = AF_INET;
local.sin_addr.s_addr = (!interface) ? INADDR_ANY : inet_addr(interface);
/*
* Port MUST be in Network Byte Order
*/
local.sin_port = htons(port);
listen_socket = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
if (listen_socket == INVALID_SOCKET){
fprintf(stderr, "socket() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if (bind(listen_socket, (struct sockaddr*)&local, sizeof(local))
== SOCKET_ERROR) {
fprintf(stderr, "TCP bind() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if (listen(listen_socket, 5) == SOCKET_ERROR) {
fprintf(stderr, "TCP listen() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
printf("TCP listen() established\n");
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (bind(udp_socket, (struct sockaddr*)&local, sizeof(local))
== SOCKET_ERROR) {
fprintf(stderr, "UDP bind() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
printf("UDP bind() established\n");
FD_ZERO(&SockSet);
maxfdp1 = max(listen_socket, udp_socket) + 1;
while (1) {
fromlen = sizeof(from);
FD_SET(listen_socket, &SockSet);
FD_SET(udp_socket, &SockSet);
if ((nready = select(maxfdp1, &SockSet, NULL, NULL, NULL)) < 0)
fprintf(stderr, "select() failed with error %d\n", WSAGetLastError());
if (FD_ISSET(listen_socket, &SockSet))
{
msgsock = accept(listen_socket, (struct sockaddr*)&from, &fromlen);
if (msgsock == INVALID_SOCKET)
{
fprintf(stderr, "accept() error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
printf("TCP msgsock=%d listen_socket=%d\n", msgsock, listen_socket);
printf("accepted connection from %s, port %d\n",
inet_ntoa(from.sin_addr),
htons(from.sin_port));
retval = recv(msgsock, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "recv() failed: error %d\n", WSAGetLastError());
closesocket(msgsock);
continue;
}
if (retval == 0) {
printf("Client closed connection\n");
closesocket(msgsock);
continue;
}
printf("Received %d bytes, data [%s] from client\n", retval, Buffer);
printf("Echoing same data back to client\n");
retval = send(msgsock, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "send() failed: error %d\n", WSAGetLastError());
}
printf("Terminating connection\n");
closesocket(msgsock);
}
else if (FD_ISSET(udp_socket, &SockSet))
{
retval = recvfrom(msgsock, Buffer, sizeof(Buffer), 0,
(struct sockaddr *)&from, &fromlen);
printf("Received datagram from %s\n", inet_ntoa(from.sin_addr));
if (retval == SOCKET_ERROR) {
fprintf(stderr, "recv() failed: error %d\n", WSAGetLastError());
closesocket(msgsock);
continue;
}
if (retval == 0) {
printf("Client closed connection\n");
closesocket(msgsock);
continue;
}
printf("Received %d bytes, data [%s] from client\n", retval, Buffer);
printf("Echoing same data back to client\n");
retval = sendto(msgsock, Buffer, sizeof(Buffer), 0,
(struct sockaddr *)&from, fromlen);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "send() failed: error %d\n", WSAGetLastError());
}
printf("UDP server looping back for more requests\n");
}
continue;
}
}
client.cpp
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_PORT 5001
#define DEFAULT_PROTO SOCK_STREAM // TCP
void Usage(char *progname) {
fprintf(stderr, "Usage\n%s -p [protocol] -n [server] -e [endpoint] \
-l [iterations]\n",
progname);
fprintf(stderr, "Where:\n\tprotocol is one of TCP or UDP\n");
fprintf(stderr, "\tserver is the IP address or name of server\n");
fprintf(stderr, "\tendpoint is the port to listen on\n");
fprintf(stderr, "\titerations is the number of loops to execute\n");
fprintf(stderr, "\t(-l by itself makes client run in an infinite loop,");
fprintf(stderr, " Hit Ctrl-C to terminate it)\n");
fprintf(stderr, "Defaults are TCP , localhost and 5001\n");
WSACleanup();
exit(1);
}
int main(int argc, char **argv) {
char Buffer[128];
char *server_name = "localhost";
unsigned short port = DEFAULT_PORT;
int retval, loopflag = 0;
int i, loopcount, maxloop = -1;
unsigned int addr;
int socket_type = DEFAULT_PROTO;
struct sockaddr_in server;
struct hostent *hp;
WSADATA wsaData;
SOCKET conn_socket;
if (argc >1) {
for (i = 1; i <argc; i++) {
if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
switch (tolower(argv[i][1])) {
case 'p':
if (!_stricmp(argv[i + 1], "TCP"))
socket_type = SOCK_STREAM;
else if (!_stricmp(argv[i + 1], "UDP"))
socket_type = SOCK_DGRAM;
else
Usage(argv[0]);
i++;
break;
case 'n':
server_name = argv[++i];
break;
case 'e':
port = (USHORT)atoi(argv[++i]);
break;
case 'l':
loopflag = 1;
if (argv[i + 1]) {
if (argv[i + 1][0] != '-')
maxloop = atoi(argv[i + 1]);
}
else
maxloop = -1;
i++;
break;
default:
Usage(argv[0]);
break;
}
}
else
Usage(argv[0]);
}
}
if ((retval = WSAStartup(0x202, &wsaData)) != 0) {
fprintf(stderr, "WSAStartup failed with error %d\n", retval);
WSACleanup();
return -1;
}
if (port == 0){
Usage(argv[0]);
}
//
// Attempt to detect if we should call gethostbyname() or
// gethostbyaddr()
if (isalpha(server_name[0])) { /* server address is a name */
hp = gethostbyname(server_name);
}
else { /* Convert nnn.nnn address to a usable one */
addr = inet_addr(server_name);
hp = gethostbyaddr((char *)&addr, 4, AF_INET);
}
if (hp == NULL) {
fprintf(stderr, "Client: Cannot resolve address [%s]: Error %d\n",
server_name, WSAGetLastError());
WSACleanup();
exit(1);
}
//
// Copy the resolved information into the sockaddr_in structure
//
memset(&server, 0, sizeof(server));
memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = htons(port);
conn_socket = socket(AF_INET, socket_type, 0); /* Open a socket */
if (conn_socket <0) {
fprintf(stderr, "Client: Error Opening socket: Error %d\n",
WSAGetLastError());
WSACleanup();
return -1;
}
printf("Client connecting to: %s\n", hp->h_name);
if (connect(conn_socket, (struct sockaddr*)&server, sizeof(server))
== SOCKET_ERROR) {
fprintf(stderr, "connect() failed: %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
loopcount = 0;
while (1) {
sprintf_s(Buffer, sizeof(Buffer), "This is a small test message [number %d]", loopcount++);
retval = send(conn_socket, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "send() failed: error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
printf("Sent Data [%s]\n", Buffer);
retval = recv(conn_socket, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "recv() failed: error %d\n", WSAGetLastError());
closesocket(conn_socket);
WSACleanup();
return -1;
}
if (retval == 0) {
printf("Server closed connection\n");
closesocket(conn_socket);
WSACleanup();
return -1;
}
printf("Received %d bytes, data [%s] from server\n", retval, Buffer);
if (!loopflag){
printf("Terminating connection\n");
break;
}
else {
if ((loopcount >= maxloop) && (maxloop >0))
break;
else
Sleep(2000);
}
}
closesocket(conn_socket);
WSACleanup();
}