I have a C program that I am trying to implement a daemon process that acts as a general TCP proxy server. I believe I have completed mostly everything correct but there is a while loop that I cannot figure out. Below is my code and I will put *** around what I am having trouble with.
Program descriptions
(1) The daemon listens for TCP connections on a specified port number.
(2) When a new client initiates a TCP connection request, the daemon accepts the request and
establishes a new TCP connection with the new client.
(a) The daemon forks a child process that is dedicated to handling the new client.
(b) The child process establishes a new TCP connection to a pre-assigned port on the actual
targeted server.
(c) The child process falls into a loop in which it acts as an intermediator exchanging data
(reading/writing or writing/reading) between the client and the targeted server.
(3) Once a child has been forked, the daemon process resumes listening for additional TCP
connections from other clients.
#ifndef unix
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define PROTOPORT 5100 /* default protocol port number */
#define QLEN 6 /* size of request queue */
int visits = 0;
int argc;
char *argv[];
int main() // works as "server" side
{
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold server's address */
struct sockaddr_in cad; /* structure to hold client's address */
int sd0, sd1; /* socket descriptors */
int port; /* protocol port number */
int addrlen; /* length of address */
pid_t pid;
memset((char *)&sad, 0, sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address(not specify, reserved */
if(argc > 1){
port = atoi(argv[1]);
}
else port = PROTOPORT; /* use the specified port number */
if (port > 0) /* test for illegal value */
sad.sin_port = htons((u_short)port);
else
{ /* print error message and exit */
fprintf(stderr,"bad port number %s\n", argv[1]);
exit(1);
}
/* Map TCP transport protocol name to protocol number */
if( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a socket */
sd0 = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if(sd0 < 0){
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Bind a local address to the socket */
// bind()
if (bind(sd0, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Listen at the port */
// listen()
/* Specify size of request queue */
if (listen(sd0, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
/* Main server loop - accept and handle requests */
while (1)
{
// accept request
addrlen = sizeof(cad);
sd1 = accept(sd0, (struct sockaddr *)&cad, &addrlen);
// fork a process
pid = fork();
if(pid == 0) // child process
{
//close oldsocket;
close(sd0);
HandleClientConnection(sd1);
break;
}
else /*parant process */
{
close(sd1);
continue;
}
}
return 0;
}
// implement "HandleClientConnection(new socket1)" - works as "client" side
HandleClientConnection(newsocket1)
{
// general socket settings at the client side
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold an IP address */
int newsocket2; /* socket descriptor */
int port; /* protocol port number */
char *host; /* pointer to host name */
int n, n2; /* number of characters read */
char buf[1000]; /* buffer for data from the server */
int i;
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
***while(1) /* get the real server's IP addr from "GET" command */
{
// read to buffer and compare, such as
if(strncmp("GET", buf[i-1], 3) == 0 || strncmp("CONNECT", buf[i-1], 7) == 0)
{
while(1)
{
//...; // read more
if(strncmp("Host", buf[i-1], 4) == 0)
{
//...;
printf("\nfound the host name.\n");
//...;
}
}
break;
}
}***
/* Convert real host name to equivalent IP address and copy to sad. */
// gethostbyname();
ptrh = gethostbyname(host);
if ( ((char *)ptrh) == NULL )
{
fprintf(stderr,"invalid host: %s\n", host);
exit(1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
/* Map TCP transport protocol name to protocol number. */
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a newsocket2. */
// socket();
newsocket2 = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (newsocket2 < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Connect the socket to the specified server. */
// connect()
if (connect(newsocket2, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"connect failed\n");
exit(1);
}
// Repeatedly read data from client (newsocket1) and write to server' side (newsocket2)
n = recv(newsocket1, buf, sizeof(buf), 0);
while (n > 0) {
write(newsocket2,buf,n);
n = recv(newsocket1, buf, sizeof(buf), 0);
}
// Repeatedly read data from server' side (newsocket2) and write to client (newsocket1).
n2 = recv(newsocket2, buf, sizeof(buf), 0);
while (n2 > 0) {
write(newsocket1,buf,n2);
n2 = recv(newsocket2, buf, sizeof(buf), 0);
}
// Close the newsocket2
close(newsocket2);
}
Related
hello i was recently given this server/client program in c that is supposed to be okay and not have any mistakes. problem is every time i try to run it i get the message the program is supposed to print when there are not enough arguments (even though i give the port number and the message i want it to echo) could anyone help me find what i am doing wrong? thank you in advance for any help you give me. the code i wanna run is the following:
server :
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#define MAXPENDING 5 /* Maximum outstanding connection requests */
#define RCVBUFSIZE 32 /*Size of receive buffer*/
void DieWithError(char *errorMessage); /* Error handling function */
void HandleTCPClient(int clntSocket);/* TCP client handling function */
int main(int argc, char *argv[]) {
int servSock; /* Socket descriptor for server */
int clntSock; /* Socket descriptor for client */
struct sockaddr_in echoServAddr; /* Local address */
struct sockaddr_in echoClntAddr; /* Client address */
unsigned short echoServPort; /* Server port */
unsigned int clntLen; /* Length of client address data structure */
if (argc != 2) {/* Test for correct number of arguments */
fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]) ;
exit(1);
}
echoServPort = atoi(argv[1]); /* First arg: local port */
/* Create socket for incoming connections */
if ((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError( "socket () failed") ;
/* Construct local address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
echoServAddr.sin_port = htons(echoServPort); /* Local port */
/* Bind to the local address */
if (bind(servSock, (struct sockaddr *)&echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError ( "bind () failed");
/* Mark the socket so it will listen for incoming connections */
if (listen(servSock, MAXPENDING) < 0)
DieWithError("listen() failed") ;
for (;;) {/* Run forever */
/* Set the size of the in-out parameter */
clntLen = sizeof(echoClntAddr);
/* Wait for a client to connect */
if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen)) < 0)
DieWithError("accept() failed");
/* clntSock is connected to a client! */
printf("Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr));
HandleTCPClient (clntSock) ;
}
/* NOT REACHED */
}
void DieWithError(char *errorMessage){
perror(errorMessage);
exit(1);
}
void HandleTCPClient(int clntSocket) {
char echoBuffer[RCVBUFSIZE];/* Buffer for echo string */
int recvMsgSize;/* Size of received message */
/* Receive message from client */
if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed") ;
/* Send received string and receive again until end of transmission */
while (recvMsgSize > 0){ /* zero indicates end of transmission */
/* Echo message back to client */
if (send(clntSocket, echoBuffer, recvMsgSize, 0) != recvMsgSize)
DieWithError("send() failed");
/* See if there is more data to receive */
if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed") ;
}
close(clntSocket); /* Close client socket */
}
the client is the following:
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#define RCVBUFSIZE 32 /* Size of receive buffer */
void DieWithError(char *errorMessage); /* Error handling function */
int main(int argc, char *argv[]) {
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
unsigned short echoServPort; /* Echo server port */
char *servIP; /* Server IP address (dotted quad) */
char *echoString; /* String to send to echo server */
char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
unsigned int echoStringLen; /* Bytes read in single recv()*/
int bytesRcvd, totalBytesRcvd; /*total bytes read */
if ((argc<3) || (argc>4)) {
fprintf(stderr, "Usage: %s <Server IP> <Echo Word> [<Echo Port>]\n", argv[0]);
exit(1);
}
servIP = argv[1] ; /* First arg' server IP address (dotted quad) */
echoString = argv[2] ;/* Second arg' string to echo */
if (argc == 4)
echoServPort = atoi(argv[3]); /* Use given port, if any */
else
echoServPort = 7; /* 7 is the well-known port for the echo service */
/* Create a reliable, stream socket using TCP */
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError(" socket () failed") ;
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
/* Establish the connection to the echo server */
if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError(" connect () failed") ;
echoStringLen = strlen(echoString) ; /* Determine input length */
/* Send the string to the server */
if (send(sock, echoString, echoStringLen, 0) != echoStringLen)
DieWithError("send() sent a different number of bytes than expected");
/* Receive the same string back from the server */
totalBytesRcvd = 0;
printf("Received: "); /* Setup to print the echoed string */
while (totalBytesRcvd < echoStringLen) {
/* Receive up to the buffer size (minus 1 to leave space for
a null terminator) bytes from the sender */
if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
DieWithError("recv() failed or connection closed prematurely");
totalBytesRcvd += bytesRcvd; /* Keep tally of total bytes */
echoBuffer[bytesRcvd] = '\0'; /* Terminate the string! */
printf(echoBuffer); /* Print the echo buffer */
}
printf("\n"); /* Print a final linefeed */
close(sock);
exit(0);
}
void DieWithError(char *errorMessage){
perror(errorMessage);
exit(1);
}
Correct me if I'm wrong, but I assume the problem is that you are inputting the wrong parameters, and are getting the "Usage: ..." error message?
Provided you compile it correctly, the programs should run with something like the following commands:
./server 1200
./client localhost message 1200
The server program accepts only 1 parameter, and the client program accepts 2 or 3 parameters. The server should also be run before the client.
I am having a small problem when trying to implement a client-server program with multithreading on the side of the server. My idea is to have the server spin forever, accept a client when it can, and just send it to a client_handle() function using a thread.
Here is the problem: my server and client are using the code seen below. At the point of the initial response of the server, it fails in sending ALL_GOOD_CD. I'm not sure why this is happening, as I print out the socket fd of the client in a line before and it seems to match up with the file descriptor given to us at the time of acception.
One thought is that my socket id is not being passed to the thread correctly. My client never seems to receive the ALL_GOOD_CD (it is blocking on a recv() call after connecting with the server). I am new with threads and sockets, anything would help; thanks!
Here is the client code needed to run:
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
void DieWithError(char *errorMessage); /* Error handling function */
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in server_addr; /* Server address */
unsigned short server_port; /* Server port */
char *server_ip; /* Server IP address (dotted quad) */
char server_response[300]; /* Buffer to hold response from the server */
char* username;
/* Test for correct number of arguments */
if (argc != 4) {
fprintf(stderr, "Usage: %s <server_ip> <server_port> <username>\n", argv[0]);
exit(1);
}
server_ip = argv[1]; /* Second arg: server IP address (dotted quad) */
server_port = atoi(argv[2]); /* Third arg: server port number */
username = argv[3]; /* Fourth arg: username */
/* Create a reliable, stream socket using TCP */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");
/* Construct the server address structure */
memset(&server_addr, 0, sizeof(server_addr)); /* Zero out structure */
server_addr.sin_family = AF_INET; /* Internet address family */
server_addr.sin_addr.s_addr = inet_addr(server_ip); /* Server IP address */
server_addr.sin_port = htons(server_port); /* Server port */
/* Establish the connection to the server */
if (connect(sock, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0)
DieWithError("connect() failed, could not find server.");
printf("connected\n");
memset(&server_response, 0, 300);
if (recv(sock, server_response, 300, 0) < 0)
DieWithError("recv() for initial response failed");
printf("received initial reponse\n");
}
void DieWithError(char* errorMessage) {
fprintf(stderr, "Dying with error sadface: %s\n", errorMessage);
exit(1);
}
Here is the server code as minified as possible:
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <pthread.h> /* multithreading the clients! */
#define MAXMSGSIZE 150
#define MAXCLIENTS 5
#define TOO_MANY_CD 0
#define ALL_GOOD_CD 1
#define OTHER_BAD_CD 2
struct client {
char* username;
char** subs;
int socket;
char temp_msg[MAXMSGSIZE*2];
};
void DieWithError(char* errorMessage); /* Error handling function */
void handle_client(void* new_socket); /* Client handling function */
static struct client** clients;
static pthread_t* threads;
static pthread_mutex_t clients_mutex;
static pthread_mutex_t threads_mutex;
int main(int argc, char *argv[])
{
int server_sock; /* Server socket descriptor */
unsigned short server_port; /* Echo server port */
struct sockaddr_in server_addr; /* sockaddr_in struct to hold information about the server */
int server_addr_size; /* Size of server_addr struct in bytes */
int client_sock;
int empty_thread;
pthread_attr_t thread_attr;
if (argc != 2) { /* Test for correct number of arguments */
fprintf(stderr, "Usage: %s <server_port>\n", argv[0]);
exit(1);
}
clients = (struct client**) calloc(1, sizeof(struct client*) * MAXCLIENTS);
if (clients == NULL)
DieWithError("calloc() for clients failed");
threads = (pthread_t*) calloc(1, sizeof(pthread_t) * MAXCLIENTS);
if (clients == NULL)
DieWithError("calloc() for clients failed");
pthread_mutex_init(&clients_mutex, NULL);
pthread_mutex_init(&threads_mutex, NULL);
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
server_port = atoi(argv[1]);
/* Create a reliable, stream socket using TCP */
if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");
// Zero out server_addr var and fill with information
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(server_port);
// Bind server with sock, IP, and port so that the clients can connect to us
if (bind(server_sock, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0)
DieWithError("bind() failed");
// Allow this server to accept 5 clients at a time (queue has 0 capacity because we multithread)
if (listen(server_sock, 0) < 0)
DieWithError("listen() failed");
// Display some information so we can connect with client
printf("Using\n\tport: %d\n\tIP: %s\n", server_port, inet_ntoa(server_addr.sin_addr));
server_addr_size = sizeof(server_addr);
for (;;) {
int* new_socket = (int*)malloc(sizeof(int));
if ((*new_socket = accept(server_sock,
(struct sockaddr*) &server_addr, &server_addr_size)) < 0) {
printf("accept() failed");
continue;
}
int free_spot = -1;
for (int i = 0; i < MAXCLIENTS; i++)
if (!threads[i]) free_spot = i;
if (free_spot == -1) {
printf("no empty threads (max clients handled currently)");
send(*new_socket,(void*) OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
close(*new_socket);
continue;
}
if (pthread_create(&threads[free_spot], &thread_attr,
(void*) &handle_client, (void*) new_socket)) {
printf("pthread_create failed");
close(*new_socket);
continue;
}
printf("sent new client %d to handle_client()\n", *new_socket);
}
}
void handle_client(void* new_socket) {
int socket = *(int*)new_socket;
free(new_socket);
printf("handling new client %d\n", socket);
struct client* curr_cl;
pthread_mutex_lock(&clients_mutex);
printf("locked mutex?\n");
if (send(socket, (void*)ALL_GOOD_CD, sizeof(ALL_GOOD_CD), 0) < 0) {
printf("inital all good resp failed");
send(socket, (void*)OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
return;
}
printf("sent stuff\n");
int free_spot = -1;
for (int i = 0; i < MAXCLIENTS; i++)
if (!clients[i]) free_spot = i;
printf("filtered through clients and got free spot %d\n", free_spot);
if (free_spot == -1) {
printf("didn't find free spot :(\n");
send(socket, (void*)TOO_MANY_CD, sizeof(TOO_MANY_CD), 0);
pthread_mutex_unlock(&clients_mutex);
return;
}
printf("found free spot %d for client %d", free_spot, socket);
clients[free_spot] = (struct client*) calloc(1, sizeof(struct client));
if (clients[free_spot] == NULL) {
send(socket, (void*)OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
pthread_mutex_unlock(&clients_mutex);
return;
}
curr_cl = clients[free_spot];
if (recv(socket, curr_cl->username, sizeof(curr_cl->username), 0) < 0) {
send(socket, (void*)OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
pthread_mutex_unlock(&clients_mutex);
return;
}
// Subscribe client to #ALL automatically
curr_cl->subs[0] = "#ALL";
if (send(socket, (void*)ALL_GOOD_CD, sizeof(ALL_GOOD_CD), 0) < 0) {
printf("send() for final all good failed\n");
send(socket, (void*)OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
pthread_mutex_unlock(&clients_mutex);
return;
}
printf("\taccepted new client %s and now listening\n", curr_cl->username);
pthread_mutex_unlock(&clients_mutex);
return;
}
void DieWithError(char* errorMessage) {
fprintf(stderr, "Dying with error sadface: %s\n", errorMessage);
exit(1);
}
Here is the Makefile
# the compiler: gcc for C
CC = gcc
# compiler flags
CFLAGS = -g
make: ttweetcl.c ttweetsrv.c
gcc -o ttweetcli ttweetcl.c && gcc -o ttweetsrv ttweetsrv.c -lpthread
.PHONY: clean
clean:
rm -f ./ttweetcli ./ttweetsrv
Solved! One comment (now removed) noticed that I was not ending my printf()'s with a \n and therefore was not flushing the buffer. Now that I have added all \n's then the code executes as it should.
This pertains to attempting to validate the return address in recvfrom() (the fifth argument to the function) in this UDP echo client:
While I can send data to the server and receive return communications correctly, I'm having trouble validating the return IP address when comparing the fromAddr.sin_addr and echoServAddr.sin_addr.
The goal here is to compare the address in the structure that was used in sendto() and the address in the structure returned from recvfrom() to validate the echo reply from the server indeed came from where the initial transmission from the client was sent (A rudimentary POC that there wasn't a Man In The Middle).
What should I be looking at in order to appropriately validate the return address as it is returned from recvfrom() matches the address transmitted to as referenced in the sendto() call?
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), sendto(), and recvfrom() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#define ECHOMAX 255 /* Longest string to echo */
void DieWithError(char *errorMessage); /* External error handling function */
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
struct sockaddr_in fromAddr; /* Source address of echo */
unsigned short echoServPort; /* Echo server port */
unsigned int fromSize; /* In-out of address size for recvfrom() */
char *servIP; /* IP address of server */
char *echoString; /* String to send to echo server */
char echoBuffer[ECHOMAX+1]; /* Buffer for receiving echoed string */
int echoStringLen; /* Length of string to echo */
int respStringLen; /* Length of received response */
// manage the command line arguments and errors
if ((argc < 3) || (argc > 4)) {
fprintf(stderr, "Usage: %s <Server IP> <Echo Word> [<Echo Port>]\n",
argv[0]);
exit(1);
}
// load servIP
servIP = argv[1];
// load echoString
echoString = argv[2];
// check echoString and error if too long
echoStringLen = strlen(echoString);
if (!(echoStringLen <= 255)) {
DieWithError("BUFFER EXCEEDED ERROR");
}
// load port
if (argc == 4)
echoServPort = atoi(argv[3]);
else
echoServPort = 7;
// create the socket
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
DieWithError("SOCKET CREATION ERROR");
}
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet addr family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
// send the string
inet_pton(AF_INET, servIP, &echoServAddr.sin_addr);
if ((sendto(sock, echoString, strlen(echoString), 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr))) < 0) {
DieWithError("SEND ERROR");
}
// recieve a response
respStringLen = recvfrom(sock, echoBuffer, sizeof(echoBuffer), 0,
(struct sockaddr *) &fromAddr, &fromSize);
if (respStringLen < 0) {
DieWithError("RECV ERROR");
}
// print the message sent
printf("SENT FROM CLIENT: '%s'\n", echoString);
// print the message recieved
echoBuffer[respStringLen] = '\0';
printf("RECEIVED FROM SERVER: '%s'\n", echoBuffer);
// check if from the correct server
if ((struct sockaddr *) &echoServAddr.sin_addr != (struct sockaddr *) &fromAddr.sin_addr) {
DieWithError("INVALID RETURN ADDRESS");
}
// close the socket
close(sock);
// exit the program
exit(0);
}
If the source IP/port of the incoming packet is the same as the destation IP/port of the packet you sent, then the sin_addr and sin_port fields of echoServAddr and fromAddr should match.
This line of code however doesn't do that:
if ((struct sockaddr *) &echoServAddr.sin_addr != (struct sockaddr *) &fromAddr.sin_addr) {
This is comparing the address of echoServAddr.sin_addr against the address of fromAddr.sin_addr. Because these are two separate variables, this will always be false. You instead want:
if ((echoServAddr.sin_addr.s_addr != fromAddr.sin_addr.s_addr) ||
(echoServAddr.sin_port != fromAddr.sin_port))
I am trying to implement the following code for a simple FTP between a client and a server. The problem is, when the server sends the file to the client, the file is empty. I'm not sure what the problem is. I'm assuming the problem lies when the server sends the file. Below is the code.
/*Server Code*/
#ifndef unix
#define WIN32
#include <windows.h>
#include <winsock.h>
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#endif
#include <stdio.h>
#include <string.h>
#define PROTOPORT 5193 /* default protocol port number */
#define QLEN 6 /* size of request queue */
int visits = 0; /* counts client connections */
main(argc, argv)
int argc;
char *argv[];
{
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold server.s address */
struct sockaddr_in cad; /* structure to hold client.s address */
int sd, sd2; /* socket descriptors */
int port; /* protocol port number */
int alen; /* length of address */
char buf_recv[1000],buf_send[1000]; /* buffer for string the server sends */
char file_buffer[10000],f_buffer[1000];
int n;
FILE *fp;
#ifdef WIN32
WSADATA wsaData;
WSAStartup(0x0101, &wsaData);
#endif
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */
if (argc > 1) { /* if argument specified */
port = atoi(argv[1]);
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for illegal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[1]);
exit(1);
}
/* Map TCP transport protocol name to protocol number */
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a socket */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Bind a local address to the socket */
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Specify size of request queue */
if (listen(sd, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
alen = sizeof(cad);
if ( (sd2=accept(sd, (struct sockaddr *)&cad, &alen)) < 0) {
fprintf(stderr, "accept failed\n");
exit(1);
}
sprintf(buf_send,"Please enter the file name: ");
send(sd2,buf_send,strlen(buf_send),0);
n=recv(sd2,buf_recv,1000,0);
buf_recv[n]='\0';
printf("%s\n",buf_recv);
fflush(stdout);
if((fp = fopen(buf_recv,"r"))==NULL)
{
sprintf(buf_send,"File could not be found!!!");
exit(0);
} else
sprintf(buf_send,"File found!!!\n");
send(sd2,buf_send,strlen(buf_send),0);
n=recv(sd2,buf_recv,1000,0);
printf("%s",buf_recv);
fflush(stdout);
while(!feof(fp)) {
fgets(f_buffer,1000,fp);
if (feof(fp))
break;
strcat(file_buffer,f_buffer);
}
fclose(fp);
send(sd2,file_buffer,strlen(file_buffer),0);
closesocket(sd2);
exit(0);
}
The Client Code:
/*Client Code*/
#ifndef unix
#define WIN32
#include <windows.h>
#include <winsock.h>
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
#include <stdio.h>
#include <string.h>
#define PROTOPORT 5193 /* default protocol port number */
extern int errno;
char localhost[] = "localhost"; /* default host name */
main(argc, argv)
int argc;
char *argv[];
{
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold an IP address */
int sd; /* socket descriptor */
int port; /* protocol port number */
char *host; /* pointer to host name */
int n; /* number of characters read */
char buf_recv[1000],buf_send[100]; /* buffer for data from the server */
char *filename;
char file_buffer[10000];
FILE *fp;
#ifdef WIN32
WSADATA wsaData;
WSAStartup(0x0101, &wsaData);
#endif
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
if (argc > 2) { /* if protocol port specified */
port = atoi(argv[2]); /* convert to binary */
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for legal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[2]);
exit(1);
}
/* Check host argument and assign host name. */
if (argc > 1) {
host = argv[1]; /* if host argument specified */
} else {
host = localhost;
}
/* Convert host name to equivalent IP address and copy to sad. */
ptrh = gethostbyname(host);
if ( ((char *)ptrh) == NULL ) {
fprintf(stderr,"invalid host: %s\n", host);
exit(1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
/* Map TCP transport protocol name to protocol number. */
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a socket. */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Connect the socket to the specified server. */
if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"connect failed\n");
exit(1);
}
n = recv(sd, buf_recv, sizeof(buf_recv), 0);
buf_recv[n]='\0';
printf("%s",buf_recv);
scanf("%s",buf_send);
send(sd,buf_send,strlen(buf_send),0);
n = recv(sd, buf_recv, sizeof(buf_recv), 0);
buf_recv[n]='\0';
printf("%s",buf_recv);
fflush(stdout);
sprintf(buf_send,"Client acknowledges, Sending file now.\n");
send(sd,buf_send, strlen(buf_send),0);
n=recv(sd, file_buffer, sizeof(file_buffer), 0);
file_buffer[n]='\0';
fflush(stdout);
fp = fopen("transferredFile.TXT","w");
fputs(file_buffer,fp);
fclose(fp);
closesocket(sd);
exit(0);
}
Is the problem coming from the server sending or is it the client receiving? Thanks!
Server: 'strcat(file_buffer,f_buffer);' - concat to uninitialized array.
Server and Client: assumptions that data contains no nulls, ie. system cannnot transfer binary data, only text.
Server and Client - assumptions that all the file data will fit in one line.
Server and Client - assumptions that TCP can transfer messages larger than one byte.
Probably other bugs associated with TCP streaming and C null-terminated strings.
Hell all. I was working on a server c project, using UDP for a whois service.
But I got error: "No whois is service on this host." Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pwd.h>
#define BACKLOG 5 /* # of requests we're willing to queue */
#define MAXHOSTNAME 32 /* maximum host name length we tolerate */
main(argc,argv)
int argc; /* standard UNIX argument declarations */
char *argv[];
{
int s,t; /* socket descriptors */
int i; /* general purpose integer */
struct sockaddr_in sa,isa; /* Internet socket address structure */
struct hostent *hp; /* result of host name lookup */
char *myname; /* pointer to name of this program */
struct servent *sp; /* result of service lookup */
char localhost[MAXHOSTNAME+1]; /* local host name as character string */
myname = argv[0];
/*
* Look up the WHOIS service entry
*/
if((sp = getservbyname("whois","udp")) == NULL){
fprintf(stderr, "%s: No whois service on this host\n", myname);
exit(1);
}
/*
* Get our own host information
*/
gethostname(localhost, MAXHOSTNAME);
if((hp = gethostbyname(localhost)) == NULL){
fprintf(stderr, "%s: cannot get local host info?\n", myname);
exit(1);
}
printf("host name is: %s\n",hp->h_name);
printf("my name is: %s\n",myname);
/*
* Put the WHOIS socket number and our address info into the socket structure
*/
u_short portbase = 0;
portbase = 5000;
sa.sin_port = sp->s_port;
sa.sin_port = htons(ntohs((u_short)sp->s_port)+portbase);
bcopy((char *)hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;
/*
* Allocate an open socket for incoming connections
*/
if((s = socket(hp->h_addrtype, SOCK_DGRAM, 0)) < 0){
perror("socket");
exit(1);
}
/*
* Bind the socket to the service port
*/
if(bind(s, (struct sockaddr *)&sa, sizeof sa) < 0){
perror("bind");
exit(1);
}
/*
* Set maximum connections we will fall behind
*/
//listen(s,BACKLOG);
/*
* Go into an infinite loop waiting for new connections
*/
while(1){
i = sizeof isa;
/*
* We hang in accept() while waiting for new customers
*/
/*
if((t = accept(s, (struct sockaddr *)&isa, &i)) < 0){
perror("accept");
exit(1);
}
*/
whois(s); /* perform the actual WHOIS service */
close(s);
}
}
/*
* Get the WHOIS request from remote host and format a reply.
*/
whois(sock)
int sock;
{
struct sockaddr_in clientAddr;
socklen_t len = sizeof(clientAddr);
memset(&clientAddr, 0, sizeof(clientAddr));
struct passwd *p;
char buf[BUFSIZ+1];
int i;
/*
* Get one line request
*/
printf("start to recv data\n");
if((i = recvfrom(sock, buf, BUFSIZ, 0, (struct sockaddr*)&clientAddr, &len)) <= 0)
printf("recv failed\n");
return;
buf[i] = '\0'; /* Null terminate */
printf("After the read, the buf is: %s \n",buf);
/*
* Look up the requested user and format reply
*/
if((p = getpwnam(buf)) == NULL)
strcpy(buf, "User not found\n");
else
sprintf(buf, "%s: %s (from me)\n", p->pw_name, p->pw_gecos);
/*
* Return reply
*/
//write(sock, buf, strlen(buf));
sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&clientAddr, len);
return;
}
I couldn't figure out where's error. I have a similar code using TCP for whois which runs no problem.
WHOIS is a TCP service. It is not available over UDP.
Additionally, what you are writing is not a WHOIS server at all. WHOIS is a protocol implemented by domain and IP registrars to communicate ownership information (e.g, to look up the owner of a domain name). What you are writing here appears to be a NIS service of some sort - this is not WHOIS, and should not use the same port.