227 lines
4.6 KiB
C++
227 lines
4.6 KiB
C++
/*
|
|
* tcpserver.c
|
|
*
|
|
* Example BSD TCP socket server.
|
|
* Paired with tcpclient.c.
|
|
*
|
|
* OS: SunOS
|
|
* compiler: cc
|
|
* % cc -o tcpserver -g tcpserver.c
|
|
*
|
|
* To run:
|
|
* % tcpserver&
|
|
* % tcpclient localhost
|
|
*
|
|
* The server listen on a #define hardwired port TCPPORT (see below).
|
|
* It accepts some number of requests from the client and turns around
|
|
* and writes those buffers back to the client.
|
|
*
|
|
* This is a simple test server. A more 'normal' server would start
|
|
* at boot and block in an accept call (or be coded for the UNIX inetd
|
|
* which is in turn different). After the accept call, the server would
|
|
* fork a child to handle the connection. This server simply handles
|
|
* one connection and exits.
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <iostream>
|
|
#include <unistd.h>
|
|
|
|
using namespace std;
|
|
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
#define TCPPORT 10000 /* server port value */
|
|
#define BUFSIZE 1024 /* size of i/o buffer */
|
|
#define NOREADS 10 /* number of buffers transferred */
|
|
|
|
/*
|
|
* create socket
|
|
* bind to address
|
|
*/
|
|
int initSocket()
|
|
{
|
|
struct sockaddr_in server;
|
|
int sock;
|
|
int optval = 1;
|
|
int retVal;
|
|
|
|
/* create INTERNET,TCP socket
|
|
*/
|
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
if ( sock < 0 ) {
|
|
perror("socket");
|
|
exit(1);
|
|
}
|
|
|
|
server.sin_family = AF_INET;
|
|
server.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
server.sin_port = htons(TCPPORT); /* specific port */
|
|
|
|
/* bind protocol to socket
|
|
*/
|
|
if (bind(sock, (struct sockaddr *) &server, sizeof(server))) {
|
|
perror("bind");
|
|
exit(1);
|
|
}
|
|
|
|
//retVal = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
|
|
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,(int *)&optval, sizeof(optval)) ;
|
|
return(sock);
|
|
}
|
|
|
|
void doWrite(int sock, char *buf)
|
|
{
|
|
int len = strlen(buf);
|
|
char slen[8];
|
|
int rc;
|
|
sprintf(slen, "%04d", len);
|
|
rc = write(sock, slen, 4);
|
|
if (rc < 0) {
|
|
perror("write");
|
|
exit(1);
|
|
}
|
|
write(sock, buf, len);
|
|
if (rc < 0) {
|
|
perror("write");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
/* read from socket. Read call issued to kernel
|
|
* may return with incomplete data. This routine
|
|
* must check that and force a complete read.
|
|
*/
|
|
void doRead(int sock, char *buf)
|
|
{
|
|
register int i;
|
|
int rc;
|
|
char *bpt;
|
|
int count;
|
|
int amountNeeded;
|
|
int amtread;
|
|
|
|
bpt = buf;
|
|
|
|
rc =0;
|
|
while (rc < 4) {
|
|
rc += read(sock, bpt, 4-rc);
|
|
bpt += rc;
|
|
}
|
|
amountNeeded = atoi(buf);
|
|
count = amountNeeded;
|
|
bpt = buf;
|
|
|
|
amtread = 0;
|
|
|
|
again:
|
|
if ( (rc = read(sock,bpt,count)) < 0 ) {
|
|
perror("doRead: reading socket stream");
|
|
exit(1);
|
|
}
|
|
amtread += rc;
|
|
|
|
if ( amtread < amountNeeded ) {
|
|
count = count - rc;
|
|
bpt = bpt + rc;
|
|
goto again;
|
|
}
|
|
buf[amountNeeded] = '\0';
|
|
}
|
|
|
|
|
|
int main(int argc,char **argv)
|
|
{
|
|
int sock;
|
|
int size;
|
|
char buf[BUFSIZE];
|
|
int msgsock;
|
|
struct sockaddr_in gotcha;
|
|
int rc;
|
|
int i;
|
|
char *cp;
|
|
char port[16];
|
|
pid_t pid;
|
|
|
|
|
|
|
|
|
|
sock = initSocket();
|
|
|
|
/* tcp starts listening for connections
|
|
*/
|
|
rc = listen(sock,5);
|
|
if ( rc < 0) {
|
|
perror("listen");
|
|
exit(1);
|
|
}
|
|
/* accept one connection, will block here.
|
|
*/
|
|
size = sizeof (struct sockaddr_in);
|
|
pid = fork();
|
|
if (pid == 0) {
|
|
//sprintf(buf, "/home/dan/src/my/gobot/gobot.sh 127.0.0.1 %d 2>&1 /dev/null\n", TCPPORT);
|
|
sprintf(buf, "/usr/bin/sbcl --noinform --load /home/dan/src/my/gobot/fink.fasl --eval '(progn (gtp-handler:gtp-net-client \"127.0.0.1\" %d) (quit))' \n", TCPPORT);
|
|
|
|
//printf("%s\n", buf);
|
|
system(buf);
|
|
return 0;
|
|
}
|
|
/* gotcha and size are returned when the connection comes in.
|
|
* When the client calls connect, and a connection occurs, accept
|
|
* returns. gotcha holds the client ip address and client port value.
|
|
* NOTE: the size parameter is a *pointer*, not an integer. The
|
|
* kernel returns the size of the socket structure in gotcha.
|
|
* This is called: "call by value-result". You have to pass in
|
|
* the size of the structure and the kernel returns the true result.
|
|
* For tcp/ip sockets the size never changes. For unix sockets
|
|
* it may change.
|
|
*/
|
|
msgsock = accept(sock, (struct sockaddr *) &gotcha, (socklen_t*)&size);
|
|
if (msgsock < 0 ) {
|
|
perror("accept");
|
|
exit(1);
|
|
}
|
|
|
|
/* read and echo so many packets
|
|
*/
|
|
/*for ( i = 0; i < NOREADS; i++) {
|
|
doRead(msgsock, buf, BUFSIZE);
|
|
rc = write(msgsock, buf, BUFSIZE);
|
|
if ( rc < 0 ) {
|
|
perror("write");
|
|
exit(1);
|
|
}
|
|
}*/
|
|
do {
|
|
cin.getline(buf, BUFSIZE);
|
|
//printf("%s", buf);
|
|
doWrite(msgsock, buf);
|
|
buf[0] = '\0';
|
|
doRead(msgsock, buf);
|
|
//printf("%s", buf);
|
|
cout << buf;
|
|
buf[0] = '\0';
|
|
} while (1);
|
|
|
|
/* close sockets
|
|
*/
|
|
close(msgsock);
|
|
close(sock);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|