commit
05d86a4456
@ -0,0 +1,90 @@
|
|||||||
|
# .SILENT:
|
||||||
|
|
||||||
|
VERSION=0.1
|
||||||
|
PREFIX=/usr/local
|
||||||
|
ETCPREFIX=/etc
|
||||||
|
|
||||||
|
CXX=g++
|
||||||
|
CXXFLAGS= -ggdb -fPIC -pg -Wno-write-strings -I./
|
||||||
|
LDFLAGS= -lm -lc -pg
|
||||||
|
|
||||||
|
DEFAULT_TCPPORT=6131
|
||||||
|
DEFAULT_UDPPORT=6131
|
||||||
|
DEFAULT_SERVER=localhost
|
||||||
|
|
||||||
|
OBJLIB=network.o udp.o tcp.o
|
||||||
|
INCLIB=config.h UDPTCPNetwork.h
|
||||||
|
OBJLIB_NAME=UDPTCPNetwork
|
||||||
|
TARGET=lib$(OBJLIB_NAME).so.$(VERSION)
|
||||||
|
|
||||||
|
DISTNAME=libUDPTCPNetwork-$(VERSION)
|
||||||
|
DEPENDFILE=.depend
|
||||||
|
|
||||||
|
all: dep $(TARGET) test-udp test-tcp
|
||||||
|
|
||||||
|
test-tcp: $(TARGET) test-tcp.o config.h
|
||||||
|
$(CXX) test-tcp.o -o $@ $(LDFLAGS) -lUDPTCPNetwork -L./ -I./
|
||||||
|
|
||||||
|
test-udp: $(TARGET) test-udp.o config.h
|
||||||
|
$(CXX) test-udp.o -o $@ $(LDFLAGS) -lUDPTCPNetwork -L./ -I./
|
||||||
|
|
||||||
|
install: $(TARGET)
|
||||||
|
cp -f $(TARGET) $(PREFIX)/lib/
|
||||||
|
ln -sf $(TARGET) $(PREFIX)/lib/lib$(OBJLIB_NAME).so
|
||||||
|
cp -f UDPTCPNetwork.h $(PREFIX)/include/
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f $(PREFIX)/lib/$(TARGET)
|
||||||
|
rm -f $(PREFIX)/lib/lib$(OBJLIB_NAME).so
|
||||||
|
rm -f $(PREFIX)/include/UDPTCPNetwork.h
|
||||||
|
|
||||||
|
rebuild: clean all
|
||||||
|
|
||||||
|
$(TARGET): $(OBJLIB) $(INCLIB)
|
||||||
|
$(CXX) -shared -Wl,-soname,lib$(OBJLIB_NAME).so -o $(TARGET) $^ -lc $(LDFLAGS)
|
||||||
|
ln -sf $(TARGET) lib$(OBJLIB_NAME).so
|
||||||
|
ar rcs lib$(OBJLIB_NAME).a $(OBJLIB)
|
||||||
|
|
||||||
|
dep:
|
||||||
|
$(CXX) -MM `ls *.cc` $(CXXFLAGS) > $(DEPENDFILE)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm test-tcp -rf
|
||||||
|
rm test-udp -rf
|
||||||
|
rm -rf gmon.out
|
||||||
|
rm *.s -rf
|
||||||
|
rm *.o -rf
|
||||||
|
rm *.oo -rf
|
||||||
|
rm *~ -rf
|
||||||
|
rm -rf config.h
|
||||||
|
rm -rf .depend
|
||||||
|
rm -rf *.so
|
||||||
|
rm -rf *.a
|
||||||
|
rm -rf *.so.*
|
||||||
|
|
||||||
|
|
||||||
|
cleanall: clean
|
||||||
|
|
||||||
|
source: cleanall
|
||||||
|
|
||||||
|
config:
|
||||||
|
echo "#ifndef _CONFIG_H_" > config.h
|
||||||
|
echo "#define _CONFIG_H_" >> config.h
|
||||||
|
echo "" >> config.h
|
||||||
|
echo "#define UDPTCPNETWORK_VERSION \"$(VERSION)\"" >> config.h
|
||||||
|
echo "" >> config.h
|
||||||
|
echo "#define PREFIX \"$(PREFIX)\"" >> config.h
|
||||||
|
echo "#define ETCPREFIX \"$(ETCPREFIX)\"" >> config.h
|
||||||
|
echo "" >> config.h
|
||||||
|
echo "#endif" >> config.h
|
||||||
|
|
||||||
|
dist: clean
|
||||||
|
mkdir -p $(DISTNAME)
|
||||||
|
cp -rf Makefile $(DISTNAME)
|
||||||
|
cp -rf *.h $(DISTNAME)
|
||||||
|
cp -rf *.cc $(DISTNAME)
|
||||||
|
tar cvzf $(DISTNAME).tgz --exclude=*/CVS/* --exclude=*/CVS/ $(DISTNAME)
|
||||||
|
rm -rf $(DISTNAME)
|
||||||
|
|
||||||
|
-include $(DEPENDFILE)
|
||||||
|
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
#ifndef _UDPTCPNETWORK_H_
|
||||||
|
#define _UDPTCPNETWORK_H_
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#define NET_HOSTLEN 256
|
||||||
|
#define NET_PORTLEN 6
|
||||||
|
#define NET_BUFFERSIZE 1024
|
||||||
|
#define NET_MAX_RETRY 5 // retry to send data EINTR
|
||||||
|
#define NET_MAX_TIMEOUT 30000 // timeout in ms
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
*
|
||||||
|
* global functions needed for networking
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int dns_filladdr (string host, string port, int ai_family,
|
||||||
|
struct sockaddr_storage *sAddr);
|
||||||
|
char *itoa(char* buffer, int number, int size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
*
|
||||||
|
* udp related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class UDP {
|
||||||
|
private:
|
||||||
|
int sock;
|
||||||
|
int localport;
|
||||||
|
size_t readcnt;
|
||||||
|
size_t writecnt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UDP();
|
||||||
|
~UDP();
|
||||||
|
|
||||||
|
int Listen(int port);
|
||||||
|
|
||||||
|
long int ReadTimeout(string *srcaddr, char *buffer, long int len, int timeout_ms);
|
||||||
|
long int Read(string *srcaddr, char *buffer, long int len);
|
||||||
|
long int Write(string destaddr, char *buffer, long int len);
|
||||||
|
|
||||||
|
void Close();
|
||||||
|
int IsListen();
|
||||||
|
int IsData(int timeout_ms); // timeout in ms;
|
||||||
|
|
||||||
|
int GetSocket() { return sock; };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* tcp related functions
|
||||||
|
*/
|
||||||
|
class TCP {
|
||||||
|
private:
|
||||||
|
int sock;
|
||||||
|
// struct sockaddr_storage localaddr;
|
||||||
|
// struct sockaddr_storage remoteaddr;
|
||||||
|
string remote_host;
|
||||||
|
string remote_port;
|
||||||
|
int readcnt;
|
||||||
|
int writecnt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TCP();
|
||||||
|
TCP(int s);
|
||||||
|
TCP(string h, string p);
|
||||||
|
TCP(string hostport, int defaultport);
|
||||||
|
~TCP();
|
||||||
|
|
||||||
|
int Connect();
|
||||||
|
int Connect(string h, string p);
|
||||||
|
int Connect(string host, int defaultport);
|
||||||
|
long int ReadPop (char *buffer, long int pktlen, long int bufferlen);
|
||||||
|
long int ReadTimeout(char *buffer, long int len, int timeout);
|
||||||
|
long int Read(char *buffer, long int len);
|
||||||
|
long int Write(char *buffer, long int len);
|
||||||
|
void Close();
|
||||||
|
int IsConnected();
|
||||||
|
int IsData(int timeout); // timeout in ms;
|
||||||
|
|
||||||
|
int Listen(int port);
|
||||||
|
TCP* Accept();
|
||||||
|
|
||||||
|
int GetSocket() { return sock; };
|
||||||
|
void SetSocket(int s, struct sockaddr_storage *saddr, int saddrlen);
|
||||||
|
|
||||||
|
const string WebGetURLHost (string url);
|
||||||
|
const string WebGetURLPort (string url);
|
||||||
|
const string WebGetURLFile (string url);
|
||||||
|
int WebGetFile (string url, char *buffer, int maxsize);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
#include "UDPTCPNetwork.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h> /* close() */
|
||||||
|
#include <string.h> /* memset() */
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
char dnsip[NET_HOSTLEN];
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// convert host and port to sockaddr_in6
|
||||||
|
//
|
||||||
|
int dns_filladdr (string host, string port, int ai_family,
|
||||||
|
struct sockaddr_storage *sAddr) {
|
||||||
|
struct addrinfo hints, *res;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
bzero (&hints, sizeof (struct addrinfo));
|
||||||
|
hints.ai_family = ai_family;
|
||||||
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
|
||||||
|
if ((err = getaddrinfo (host.c_str(), port.c_str(), &hints, &res)) < 0) {
|
||||||
|
fprintf (stdout, "dns_filladdr (getaddrinfo):%s\n", gai_strerror (err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (sAddr, res->ai_addr, res->ai_addrlen);
|
||||||
|
freeaddrinfo (res);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// convert int to char*
|
||||||
|
//
|
||||||
|
char* itoa(char* buffer, int number, int size) {
|
||||||
|
snprintf (buffer, size, "%d", number);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
@ -0,0 +1,401 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h> /* close() */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h> /* memset() */
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "UDPTCPNetwork.h"
|
||||||
|
|
||||||
|
TCP::~TCP() {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
TCP::TCP() {
|
||||||
|
sock = 0;
|
||||||
|
writecnt = 0;
|
||||||
|
readcnt = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
TCP::TCP(int s) {
|
||||||
|
TCP();
|
||||||
|
sock = s;
|
||||||
|
// memset (&localaddr, 0x0, sizeof(localaddr));
|
||||||
|
// memset (&remoteaddr, 0x0, sizeof(remoteaddr));
|
||||||
|
writecnt = 0;
|
||||||
|
readcnt = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
TCP::TCP(string h, string p) {
|
||||||
|
TCP();
|
||||||
|
Connect (h,p);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int TCP::Listen(int port) {
|
||||||
|
char buffer[NET_BUFFERSIZE];
|
||||||
|
int err, i;
|
||||||
|
struct addrinfo hints, *res, *rp;
|
||||||
|
|
||||||
|
if (sock > 0) Close();
|
||||||
|
|
||||||
|
bzero (&hints, sizeof (struct addrinfo));
|
||||||
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
hints.ai_family = AF_INET6;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
if ((err = getaddrinfo (NULL, itoa(buffer, port, 32), &hints, &res)) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// walk through all results until we could connect
|
||||||
|
//
|
||||||
|
for (rp = res; rp != NULL; rp = rp->ai_next) {
|
||||||
|
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||||
|
if (sock == -1) continue;
|
||||||
|
|
||||||
|
if ((err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i))) != 0) {
|
||||||
|
printf ("%s:%d setsockopt error\n", __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
if ((err = bind (sock, rp->ai_addr, rp->ai_addrlen)) < 0) {
|
||||||
|
close (sock);
|
||||||
|
sock = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (listen (sock, 8) < 0) {
|
||||||
|
close (sock);
|
||||||
|
sock = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo (res);
|
||||||
|
|
||||||
|
if (rp == NULL) {
|
||||||
|
sock = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TCP* TCP::Accept() {
|
||||||
|
fd_set rfds;
|
||||||
|
struct timeval tv;
|
||||||
|
int retval, newsock, err, i;
|
||||||
|
struct sockaddr_storage cli_addr;
|
||||||
|
unsigned int cli_len;
|
||||||
|
char host[NET_BUFFERSIZE];
|
||||||
|
char port[NET_BUFFERSIZE];
|
||||||
|
TCP *tcp = NULL;
|
||||||
|
|
||||||
|
if (sock <= 0) return NULL;
|
||||||
|
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(sock, &rfds);
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
retval = select (sock+1, &rfds, NULL, NULL, &tv);
|
||||||
|
if (retval == -1 && errno == EINTR) {
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
else if (retval == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (retval) {
|
||||||
|
newsock = accept (sock, (struct sockaddr *) &cli_addr, &cli_len);
|
||||||
|
if (newsock < 0) return NULL;
|
||||||
|
|
||||||
|
tcp = new TCP();
|
||||||
|
tcp->SetSocket(newsock, &cli_addr, cli_len);
|
||||||
|
return tcp;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int TCP::Connect(string h, string p) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
// memset (&localaddr, 0x0, sizeof(localaddr));
|
||||||
|
// memset (&remoteaddr, 0x0, sizeof(remoteaddr));
|
||||||
|
// i = dns_filladdr(h, p, AF_INET, &remoteaddr);
|
||||||
|
// if (i == 0) return 0;
|
||||||
|
remote_host = h;
|
||||||
|
remote_port = p;
|
||||||
|
|
||||||
|
return Connect();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int TCP::Connect(string hostport, int defaultport) {
|
||||||
|
char buffer[32];
|
||||||
|
int pos = hostport.rfind(':', hostport.length());
|
||||||
|
if (pos == -1) {
|
||||||
|
remote_port = itoa (buffer, defaultport, 32);
|
||||||
|
remote_host = hostport;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
remote_port = hostport.substr (pos+1, hostport.length() - pos);
|
||||||
|
remote_host = hostport.substr (0, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Connect();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int TCP::Connect() {
|
||||||
|
int err, s;
|
||||||
|
struct addrinfo hints, *res, *rp;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = 0;
|
||||||
|
hints.ai_protocol = 0;
|
||||||
|
|
||||||
|
s = getaddrinfo(remote_host.c_str(), remote_port.c_str(), &hints, &res);
|
||||||
|
if (s != 0) {
|
||||||
|
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// walk through all results until we could connect
|
||||||
|
//
|
||||||
|
for (rp = res; rp != NULL; rp = rp->ai_next) {
|
||||||
|
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||||
|
if (sock == -1) continue;
|
||||||
|
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) break;
|
||||||
|
close(sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(res);
|
||||||
|
|
||||||
|
//
|
||||||
|
// connect not successfull
|
||||||
|
//
|
||||||
|
if (rp == NULL) return 0;
|
||||||
|
|
||||||
|
writecnt = 0;
|
||||||
|
readcnt = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
long int TCP::ReadPop (char *buffer, long int pktlen, long int bufferlen) {
|
||||||
|
memmove (buffer, buffer+pktlen, bufferlen-pktlen);
|
||||||
|
return bufferlen-pktlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long int TCP::Read(char *buffer, long int len) {
|
||||||
|
long int len_ = len;
|
||||||
|
|
||||||
|
if (sock <= 0) return -2;
|
||||||
|
len_ = read (sock, (void*)buffer, len);
|
||||||
|
// printf ("read: "); debug_mem(buffer, len_);
|
||||||
|
|
||||||
|
if (len_ < 0 && errno == EAGAIN) len_ = 0;
|
||||||
|
else if (len_ < 0 && errno != EAGAIN) {
|
||||||
|
// fprintf (stderr, "%s ERROR:%s\n", __FUNCTION__, strerror (errno));
|
||||||
|
len_ = -2;
|
||||||
|
}
|
||||||
|
else if (len_ == 0) len_ = -1;
|
||||||
|
if (len_ < 0) Close();
|
||||||
|
|
||||||
|
readcnt += len_;
|
||||||
|
|
||||||
|
return len_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
long int TCP::ReadTimeout(char *buffer, long int len, int timeout) {
|
||||||
|
int data = IsData (timeout);
|
||||||
|
|
||||||
|
if (data > 0) return Read (buffer, len);
|
||||||
|
else if (data < 0) return -1;
|
||||||
|
else return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
long int TCP::Write(char *buffer, long int len) {
|
||||||
|
int i;
|
||||||
|
int to = NET_MAX_RETRY;
|
||||||
|
|
||||||
|
if (sock <= 0) return -1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
i = send (sock, buffer, len, 0);
|
||||||
|
} while (i == -1 && (to--) > 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (i < 0) Close ();
|
||||||
|
writecnt += i;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void TCP::Close() {
|
||||||
|
if (sock > 0) close (sock);
|
||||||
|
sock = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void TCP::SetSocket(int s, struct sockaddr_storage *saddr, int saddrlen) {
|
||||||
|
char host[NET_HOSTLEN];
|
||||||
|
char port[NET_PORTLEN];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
|
||||||
|
if (sock > 0) Close();
|
||||||
|
if (s > 0) {
|
||||||
|
sock = s;
|
||||||
|
|
||||||
|
if (saddr != NULL) {
|
||||||
|
if ((err = getnameinfo ((struct sockaddr*) &saddr, saddrlen, host, NET_HOSTLEN,
|
||||||
|
port, NET_PORTLEN, NI_NUMERICHOST | NI_NUMERICSERV)) == 0) {
|
||||||
|
remote_host = host;
|
||||||
|
remote_port = port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else sock = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int TCP::IsConnected() {
|
||||||
|
return (sock > 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int TCP::IsData(int timeout) {
|
||||||
|
fd_set sockset;
|
||||||
|
struct timeval tval;
|
||||||
|
|
||||||
|
if (sock <= 0) return -1;
|
||||||
|
|
||||||
|
FD_ZERO (&sockset);
|
||||||
|
FD_SET (sock, &sockset);
|
||||||
|
tval.tv_sec = timeout / 1000;
|
||||||
|
tval.tv_usec = (timeout % 1000);
|
||||||
|
if ((select (sock + 1, &sockset, NULL, NULL, &tval)) != -1) {
|
||||||
|
if (FD_ISSET (sock, &sockset)) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (errno == EBADF) sock = -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int TCP::WebGetFile (string url, char *buffer, int maxsize) {
|
||||||
|
char outdata[NET_BUFFERSIZE];
|
||||||
|
char indata[NET_BUFFERSIZE];
|
||||||
|
char host[NET_HOSTLEN];
|
||||||
|
char port[NET_PORTLEN];
|
||||||
|
int breakup, len, head, i, buffpos = 0;
|
||||||
|
|
||||||
|
if (!IsConnected()) {
|
||||||
|
strncpy (host, WebGetURLHost (url).c_str(), NET_HOSTLEN);
|
||||||
|
strncpy (port, WebGetURLPort (url).c_str(), NET_PORTLEN);
|
||||||
|
Connect (host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsConnected()) return -1;
|
||||||
|
|
||||||
|
// send http request
|
||||||
|
snprintf (outdata, NET_BUFFERSIZE, "GET %s HTTP/1.0\nUser-Agent: tcpclient \nHost: %s\n\n", WebGetURLFile (url).c_str(), host);
|
||||||
|
Write (outdata, strlen (outdata));
|
||||||
|
|
||||||
|
// wait for data start
|
||||||
|
i = breakup = 0;
|
||||||
|
head = 1;
|
||||||
|
while (!breakup && head && (len = ReadTimeout (indata, NET_BUFFERSIZE-1, 2000)) >= 0) {
|
||||||
|
indata[len] = 0;
|
||||||
|
while (i < len -4 && head && !breakup) {
|
||||||
|
if (indata[i] == 0x0d && indata [i+1] == 0x0a && indata [i+2] == 0x0d && indata [i+3] == 0x0a) {
|
||||||
|
head = 0;
|
||||||
|
i = i + 4;
|
||||||
|
buffpos = len-i;
|
||||||
|
if (buffpos > maxsize) buffpos = maxsize;
|
||||||
|
memcpy (buffer, indata+i, buffpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strncmp (indata+i, "Content-Length:", 15) == 0) {
|
||||||
|
i = i + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strncmp (indata+i, "403 ", 4) == 0) breakup = 1;
|
||||||
|
else i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read data
|
||||||
|
while (!breakup && (len = ReadTimeout (indata, NET_BUFFERSIZE-1, 2000)) >= 0) {
|
||||||
|
i = len;
|
||||||
|
if (i > maxsize-buffpos) i = maxsize-buffpos;
|
||||||
|
if (i > 0) {
|
||||||
|
memcpy (buffer+buffpos, indata, i);
|
||||||
|
buffpos += i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffpos;
|
||||||
|
};
|
||||||
|
|
||||||
|
const string TCP::WebGetURLHost (string url) {
|
||||||
|
string result;
|
||||||
|
int posSServPort = 7; // begin server:port
|
||||||
|
int posEServPort = 0; // end Server:Port
|
||||||
|
int posPort = -1; // port Position
|
||||||
|
|
||||||
|
posEServPort = url.find("/", 7);
|
||||||
|
result = url.substr (posSServPort, posEServPort-posSServPort);
|
||||||
|
posPort = result.find(":");
|
||||||
|
if (posPort > 0)
|
||||||
|
result = url.substr (posSServPort, posPort);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
const string TCP::WebGetURLPort (string url) {
|
||||||
|
string result;
|
||||||
|
int posSServPort = 7; // begin server:port
|
||||||
|
int posEServPort = 0; // end Server:Port
|
||||||
|
int posPort = -1; // port Position
|
||||||
|
|
||||||
|
posEServPort = url.find("/", 7);
|
||||||
|
result = url.substr (posSServPort, posEServPort-posSServPort);
|
||||||
|
posPort = result.find(":");
|
||||||
|
if (posPort > 0)
|
||||||
|
result = result.substr (posPort+1);
|
||||||
|
else
|
||||||
|
result = "80";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
const string TCP::WebGetURLFile (string url) {
|
||||||
|
string result;
|
||||||
|
int posEServPort = 0; // end Server:Port
|
||||||
|
|
||||||
|
posEServPort = url.find("/", 7);
|
||||||
|
result = url.substr (posEServPort);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
@ -0,0 +1,123 @@
|
|||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "UDPTCPNetwork.h"
|
||||||
|
|
||||||
|
#define DEFAULT_PORT 12345
|
||||||
|
|
||||||
|
|
||||||
|
void server () {
|
||||||
|
TCP tcpserver;
|
||||||
|
TCP *connection;
|
||||||
|
int i, timeout;
|
||||||
|
pid_t pid;
|
||||||
|
char buffer[NET_BUFFERSIZE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// start the server
|
||||||
|
if (tcpserver.Listen(DEFAULT_PORT) != 1) {
|
||||||
|
printf ("cloud not start the tcp server\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// check for connections
|
||||||
|
for (timeout = 5; timeout > 0; timeout--) {
|
||||||
|
connection = tcpserver.Accept();
|
||||||
|
if (connection != NULL) {
|
||||||
|
//
|
||||||
|
// someone connected - create new process
|
||||||
|
// take care of parallel processing (parent is always the server)
|
||||||
|
//
|
||||||
|
printf (" server: got a connection forking new process\n");
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
//
|
||||||
|
// child process - always close server since it will handeled
|
||||||
|
// by the parent process. Make sure the client exits and never
|
||||||
|
// returns.
|
||||||
|
tcpserver.Close();
|
||||||
|
i = connection->ReadTimeout(buffer, NET_BUFFERSIZE, 1000);
|
||||||
|
if (i > 0) {
|
||||||
|
int c;
|
||||||
|
|
||||||
|
printf (" server: (child) got: '%s'\n", buffer);
|
||||||
|
for (c = 0; c < i; c++) buffer[c] = toupper(buffer[c]);
|
||||||
|
connection->Write(buffer, i);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// just delete the class object, it will close the client connection
|
||||||
|
delete (connection);
|
||||||
|
|
||||||
|
//
|
||||||
|
// exit child process
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//
|
||||||
|
// parent process - just close the client connection
|
||||||
|
// it will be handeled by the child process.
|
||||||
|
delete (connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sleep (1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void client () {
|
||||||
|
TCP tcpclient;
|
||||||
|
char buffer[NET_BUFFERSIZE];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sleep (1); // wait one second to start the server
|
||||||
|
|
||||||
|
//
|
||||||
|
// connect to the server
|
||||||
|
if (tcpclient.Connect ("localhost", DEFAULT_PORT) != 1) {
|
||||||
|
printf ("cloud not connect to server\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// send some data
|
||||||
|
snprintf (buffer, NET_BUFFERSIZE, "nur ein kleiner Test.");
|
||||||
|
printf ("client:send '%s' to the server.\n", buffer);
|
||||||
|
if (tcpclient.Write(buffer, strlen (buffer)) != strlen (buffer)) {
|
||||||
|
printf ("could not send all data.\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// read some data (wait maximum 10x1000ms)
|
||||||
|
for (i = 10; i > 0; i--)
|
||||||
|
if (tcpclient.ReadTimeout(buffer, NET_BUFFERSIZE, 1000) > 0) {
|
||||||
|
printf ("client:got '%s' from server.\n", buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// close connection
|
||||||
|
tcpclient.Close();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char **argv) {
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) { // child process
|
||||||
|
client();
|
||||||
|
client();
|
||||||
|
client();
|
||||||
|
client();
|
||||||
|
}
|
||||||
|
else { // parent process
|
||||||
|
server();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "UDPTCPNetwork.h"
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* server: only converts one message to upper cases and quits
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Server {
|
||||||
|
private:
|
||||||
|
UDP udp;
|
||||||
|
public:
|
||||||
|
Server() { udp.Listen(12345); };
|
||||||
|
~Server() {};
|
||||||
|
void Loop();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void Server::Loop() {
|
||||||
|
char buffer[NET_BUFFERSIZE];
|
||||||
|
int i;
|
||||||
|
string srcaddr;
|
||||||
|
|
||||||
|
udp.ReadTimeout (&srcaddr, buffer, NET_BUFFERSIZE, 2000);
|
||||||
|
printf (" server got : %s from: '%s'\n", buffer, srcaddr.c_str());
|
||||||
|
for (i = 0; i < NET_BUFFERSIZE && buffer[i] != 0; i++)
|
||||||
|
buffer[i] = toupper (buffer[i]);
|
||||||
|
printf (" server send: %s to: '%s'\n", buffer, srcaddr.c_str());
|
||||||
|
udp.Write(srcaddr, buffer, i+1);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* client: sends just one little text to the udp server
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Client {
|
||||||
|
private:
|
||||||
|
UDP udp;
|
||||||
|
public:
|
||||||
|
Client() { udp.Listen(12346); };
|
||||||
|
~Client() {};
|
||||||
|
void Loop();
|
||||||
|
};
|
||||||
|
|
||||||
|
void Client::Loop() {
|
||||||
|
char buffer[NET_BUFFERSIZE];
|
||||||
|
string srcaddr = "localhost:12345";
|
||||||
|
|
||||||
|
sprintf (buffer, "only some test.");
|
||||||
|
|
||||||
|
printf ("client send: %s to: '%s'\n", buffer, srcaddr.c_str());
|
||||||
|
udp.Write(srcaddr, buffer, strlen (buffer));
|
||||||
|
udp.ReadTimeout(&srcaddr, buffer, NET_BUFFERSIZE, 2000);
|
||||||
|
printf ("client got : %s from: '%s'\n", buffer, srcaddr.c_str());
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* udp test application:
|
||||||
|
*
|
||||||
|
* creating a server and a client object. Where the client send some text
|
||||||
|
* to the server who converts it to upper case and sends it back to the
|
||||||
|
* client.
|
||||||
|
*
|
||||||
|
* Due to forking, both processes are running separated from each other and
|
||||||
|
* are NOT checked with waitforpid. So make sure you kill them yourself.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int main (int argc, char **argv) {
|
||||||
|
Server server;
|
||||||
|
Client client;
|
||||||
|
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) { // child process
|
||||||
|
client.Loop ();
|
||||||
|
}
|
||||||
|
else { // parent process
|
||||||
|
server.Loop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "UDPTCPNetwork.h"
|
||||||
|
|
||||||
|
int main (int argc, char **argv) {
|
||||||
|
UDP udp;
|
||||||
|
char buffer[256] = "Hallo";
|
||||||
|
|
||||||
|
udp.Listen(12345);
|
||||||
|
snprintf (buffer, 256, "ein test, Parameter 0:%s", argv[0]);
|
||||||
|
|
||||||
|
udp.Write("www.gulpe.de:12345", buffer, strlen (buffer));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h> /* close() */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h> /* memset() */
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "UDPTCPNetwork.h"
|
||||||
|
|
||||||
|
UDP::UDP() {
|
||||||
|
sock = -1;
|
||||||
|
localport = -1;
|
||||||
|
writecnt = 0;
|
||||||
|
readcnt = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
UDP::~UDP() {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UDP::Close () {
|
||||||
|
if (sock > -1) close (sock);
|
||||||
|
sock = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int UDP::Listen(int port) {
|
||||||
|
struct sockaddr_in servAddr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// socket creation
|
||||||
|
//
|
||||||
|
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||||
|
printf("%s: socket error: %s \n",__FUNCTION__, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// bind local server port
|
||||||
|
//
|
||||||
|
localport = port;
|
||||||
|
servAddr.sin_family = AF_INET;
|
||||||
|
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
servAddr.sin_port = htons(localport);
|
||||||
|
if (bind (sock, (struct sockaddr *) &servAddr,sizeof(servAddr)) < 0) {
|
||||||
|
printf("%s: bind error: %s \n",__FUNCTION__, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long int UDP::ReadTimeout(string *source, char *buffer, long int len, int timeout_ms) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = IsData(timeout_ms);
|
||||||
|
if (i > 0) {
|
||||||
|
return Read (source, buffer, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
long int UDP::Read(string *source, char *buffer, long int len) {
|
||||||
|
int n;
|
||||||
|
socklen_t addrlen;
|
||||||
|
sockaddr_in srcAddr;
|
||||||
|
|
||||||
|
if (!IsListen()) return -1;
|
||||||
|
|
||||||
|
memset(buffer, 0x0, len);
|
||||||
|
|
||||||
|
addrlen = sizeof(srcAddr);
|
||||||
|
n = recvfrom(sock, buffer, len, 0, (sockaddr *) &srcAddr, &addrlen);
|
||||||
|
if(n<0) {
|
||||||
|
printf("%s: recvfrom error:%s\n",__FUNCTION__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*source) = inet_ntoa(srcAddr.sin_addr);
|
||||||
|
(*source) = (*source) + ":" + to_string (htons(srcAddr.sin_port));
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long int UDP::Write(string destaddr, char *buffer, long int len) {
|
||||||
|
int s;
|
||||||
|
int addrlen = sizeof (struct sockaddr_in);
|
||||||
|
struct sockaddr_storage dstAddr;
|
||||||
|
string host;
|
||||||
|
string port;
|
||||||
|
|
||||||
|
if (!IsListen()) {
|
||||||
|
/* socket creation */
|
||||||
|
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||||
|
printf("%s: socket error: %s \n",__FUNCTION__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else s = sock;
|
||||||
|
|
||||||
|
int pos = destaddr.rfind(':', destaddr.length());
|
||||||
|
if (pos == -1) {
|
||||||
|
port = "NET_PORT";
|
||||||
|
host = destaddr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
port = destaddr.substr (pos+1, destaddr.length() - pos);
|
||||||
|
host = destaddr.substr (0, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_filladdr (host, port, PF_INET, &dstAddr);
|
||||||
|
if (sendto (s, buffer, len, 0, (sockaddr *) &dstAddr, addrlen) == -1) {
|
||||||
|
printf("%s: sendto error: %s \n",__FUNCTION__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsListen()) close (s);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDP::IsListen() {
|
||||||
|
return (sock != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDP::IsData(int timeout_ms) {
|
||||||
|
fd_set sockset;
|
||||||
|
struct timeval tval;
|
||||||
|
|
||||||
|
if (sock <= 0) {
|
||||||
|
printf ("isData:socket error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO (&sockset);
|
||||||
|
FD_SET (sock, &sockset);
|
||||||
|
tval.tv_sec = timeout_ms / 1000;
|
||||||
|
tval.tv_usec = (timeout_ms % 1000);
|
||||||
|
if (select (sock + 1, &sockset, NULL, NULL, &tval) >= 0) {
|
||||||
|
if (FD_ISSET (sock, &sockset)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in new issue