I am getting a seg fault before main even runs. I am rusty with c and cannot find the error. Previous searches have said that if a struct is too large this can happen. I am using addrinfo, and as you can see I've tried malloc'ing it and I still seg fault before main
#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 <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#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 addrinfo hints, *servInfo; /*holds the result of getaddrinfo */
int rttOption; /* Echo server port */
char *servIP; /* Server IP address (dotted quad) */
char *portNumber; /* String to send to echo server */
char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
unsigned int echoStringLen; /* Length of string to echo */
int bytesRcvd, totalBytesRcvd; /* Bytes read in single recv() and total bytes read */
int status;
servInfo = (struct addrinfo *) malloc (sizeof(struct addrinfo));
char *httpGetRequest = "GET /";
char *partOfRequest = "HTTP/1.0\r\nConnection: keep-alive\r\n\r\n";
strcpy(httpGetRequest, servIP);
strcpy(httpGetRequest, partOfRequest);
echoStringLen = strlen(httpGetRequest);
if ((argc < 3) || (argc > 4)) /* Test for correct number of arguments */
{
fprintf(stderr, "Usage: %s <Server URL/IP> <Port Number> [<Option -p>]\n",
argv[0]);
exit(1);
}
printf("Check after parsing");
servIP = argv[1]; /* First arg: server IP address (dotted quad) */
portNumber = argv[2]; /* Second arg: string to echo */
if (argc == 4 && *argv[3] == 'p')
{
rttOption = 1; //print out the rtt
}
/* Construct the server address structure */
memset(&hints, 0, sizeof(hints)); /* Zero out structure */
hints.ai_family = AF_UNSPEC; /* Internet address family */
hints.ai_socktype = SOCK_STREAM;
//getting the linked list?
if(status = getaddrinfo(servIP, portNumber, &hints, &servInfo) < 0)
{
DieWithError("getaddrinfo() failed");
}
/* Create a reliable, stream socket using TCP */
if ((sock = socket(servInfo->ai_family, servInfo->ai_socktype, servInfo->ai_protocol)) < 0)
{
DieWithError("socket() failed");
}
/* Establish the connection to the echo server */
if (connect(sock, servInfo->ai_addr, servInfo->ai_addrlen) < 0)
{
DieWithError("connect() failed");
}
printf("Check");
/* Send the string to the server */
if (send (sock, httpGetRequest, 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, httpGetRequest, 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("%s", httpGetRequest); /* Print the echo buffer */
}
printf("\n"); /* Print a final linefeed */
close(sock);
exit(0);
return 0;
}
I expect getting at least hitting the error catch for command line inputs. But instead we are core dumping before we get there.
You don't initialize servIP before using it.
This line causes the issue:
strcpy(httpGetRequest, servIP);
You also cannot modify httpGetRequest.
The line above also causes this issue.
Allocate memory for httpGetRequest in some way, and, combined with the other change, your code is fine.
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.
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 have two files: tcp-demo-client.c and tcp-demo-server.c
Functionality: If the connection succeeds, the client receives a simple timestamp from the server. I like to modify the code that the server only sends the timestamp if the client hits the space key. How can I do that?
(It's my first socket project)
tcp-demo-client.c:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
int main(int argc, char **argv)
{
int ret; // return value from functions
// Check command line arguments
if (argc != 3) {
fprintf(stderr,
"Missing parameters. Usage: %s <server-name-or-ip> <server-port>\n",
argv[0]);
return 1;
}
// Address information structure
struct addrinfo aii;
// Set whole structure to 0s
memset(&aii, 0, sizeof(aii));
// A stream (TCP) connection
aii.ai_socktype = SOCK_STREAM;
// We do not care whether it is IPv4 or IPv6
aii.ai_family = PF_UNSPEC;
struct addrinfo *aio;
// Get address information.
// First parameter is host string, either hostname or numerical IPv4/IPv6 address
// Second parameter is port/service string, either as port number
// or well-known identifier, e.g. http
// So, e.g. getaddrinfo( "www.compeng.uni-frankfurt.de", "http", ... getaddrinfo( "141.2.248.1", "80", ...
// Third parameter is input address info structure (cf. above)
// Fourth parameter is output address info structure, a linked list of potential addresses
ret = getaddrinfo(argv[1], argv[2], &aii, &aio);
if (ret) {
fprintf(stderr, "Error getting address for %s:%s: %s\n",
argv[1], argv[2], gai_strerror(ret));
return 1;
}
// File descriptor for the socket
int sock = -1;
struct addrinfo *iter;
// Iterate over linked list of specified output addresses,
// use first address to which a connection can be established
for (iter = aio; iter != NULL && sock == -1; iter = iter->ai_next) {
// Create socket given the parameters from the found address info.
sock =
socket(iter->ai_family, iter->ai_socktype,
iter->ai_protocol);
if (sock < 0)
continue; // Appropriate socket could not be created, try next address
// Socket created successfully, now try to connect to remote target address
// taken from address info
ret = connect(sock, iter->ai_addr, iter->ai_addrlen);
if (ret) {
// Socket could not be connected to remote target
close(sock); // Close socket
sock = -1;
continue; // try next address
}
}
freeaddrinfo(aio); // Release address information allocated in getaddrinfo
if (sock == -1) {
// No connection at all could be established to remote target
fprintf(stderr, "Unable to establish any connection to %s:%s\n",
argv[1], argv[2]);
return 1;
}
// Maximum size of incoming message
int msglen = 100;
// Buffer for message
char buf[msglen + 1]; // One more to ensure that there is a trailing NULL char.
memset(buf, 0, msglen + 1);
ret = read(sock, buf, msglen); // Return value is amount of bytes read, -1 in case of error
printf("Data read: '%s'\n", buf);
// Clean up after us and close the socket.
close(sock);
return 0;
}
tcp-demo-server.c:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#define MAXPENDING 5
int main(int argc, char **argv)
{
unsigned short listen_port; // Server port */
int listen_sock; // Socket descriptor for server
int client_sock; // Socket descriptor for client
struct sockaddr_in listen_addr; // Local address */
struct sockaddr_in client_addr; // Client address */
// Check command line arguments
if (argc != 2) {
fprintf(stderr, "Missing parameters. Usage: %s <server-port>\n",
argv[0]);
return 1;
}
// Create socket for incoming connections
if ((listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket() failed");
return 1;
}
// Construct local address structure
listen_port = atoi(argv[1]); // First arg: listening port number
memset(&listen_addr, 0, sizeof(listen_addr)); // Zero out structure
listen_addr.sin_family = AF_INET; // Internet address family
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface
listen_addr.sin_port = htons(listen_port); // Local port
// Bind to the local address
if (bind
(listen_sock, (struct sockaddr *)&listen_addr,
sizeof(listen_addr)) < 0) {
perror("bind() failed");
return 1;
}
// Mark the socket so it will listen for incoming connections
if (listen(listen_sock, MAXPENDING) < 0) {
perror("listen() failed");
return 1;
}
for (;;) { /* Run forever */
socklen_t addr_len = sizeof(client_addr);
// Wait for a client to connect */
if ((client_sock =
accept(listen_sock, (struct sockaddr *)&client_addr,
&addr_len)) < 0) {
perror("accept() failed");
return 1;
}
// client_sock is connected to a client
printf("New connection from %s\n",
inet_ntoa(client_addr.sin_addr));
// Create message to send
time_t t = time(NULL);
char *msg = ctime(&t);
int msglen = strlen(msg) + 1;
int ret;
// Write the whole message in one go, fail if this does not work
ret = write(client_sock, msg, msglen);
// Return value is amount of bytes written, -1 in case of error
if (ret != msglen) {
perror("Error during write");
return 1;
}
close(client_sock);
}
/* NOT REACHED */
return 1;
}
I presume you mean you want the space char as unbuffered input. For POSIX, you could use something along the lines of this to capture the keypress:
#include <termios.h>
[...]
struct termios t;
int c, r;
[...]
tcgetattr(0, &t);
t.c_lflag &= ~(ICANON | ECHO);
t.c_cc[VMIN] = 1;
tcsetattr(0, TCSANOW, &t);
c = getchar();
r = send(sock, c, 1, 0);
Have a look at this for additional information:
setvbuf not able to make stdin unbuffered
http://c-faq.com/osdep/cbreak.html
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.
Used strtok to parse a string and now I am having difficulties with my IF statement. Suspect that I am using the wrong case (value vs. address) but I have run out of ideas. Any help would be greatly appreciated.
I used a series of printf to confirm that strtok populated "hldType" correctly. Thanks again for any help. I have been stuck on this for days.
The abbreviated code is below. The full code source is also included.
char *hldType; /* Parsing holding field */
static const char *REQTYPE = "0"; /* Comparison */
hldType = strtok(echoBuffer, "."); /* Parse the string */
if (strcmp(hldType,REQTYPE) == 0) /* NOT WORKING */
printf("REQTYPE myString: %s\n", REQTYPE);
CODE:
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket() and bind() */
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <time.h> /* Display time */
#define ECHOMAX 255 /* Longest string to echo */
void DieWithError(char *errorMessage); /* External error handling function */
/* User Defined type */
typedef struct _ServerMessage{
enum {New, Old, No_Message} messageType; /* same size as an unsigned int */
unsigned int SenderId; /* unique client identifier */
unsigned int RecipientId; /* unique client identifier */
char message[100]; /* text message */
} ServerMessage; /* an unsigned int is 32 bits = 4 bytes */
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in echoServAddr; /* Local address */
struct sockaddr_in echoClntAddr; /* Client address */
unsigned int cliAddrLen; /* Length of incoming message */
char echoBuffer[ECHOMAX]; /* Buffer for echo string */
unsigned short echoServPort; /* Server port */
int recvMsgSize; /* Size of received message */
char *hldType; /* Parsing holding field */
char *hldSend; /* Parsing holding field */
char *hldRecip; /* Parsing holding field */
char *hldMsg; /* Parsing holding field */
char tmpType[1]; /* Type of action requested by client, where 0 is Send and 1 is Received */
static const char *REQTYPE = "0";
/* Test Struct */
/*ServerMessage ServerMessage_new = {No_Message, 1234,5678,"Hello Server World - No Message"}; */
ServerMessage ServerMessage_new[100];
/* printf("Message Type: %d\n", ServerMessage_new.messageType);
printf("Message SenderID: %04d\n", ServerMessage_new.SenderId);
printf("Message RecipentID: %04d\n", ServerMessage_new.RecipientId);
printf("Message Content: %s\n", ServerMessage_new.message); */
if (argc != 2) /* Test for correct number of parameters */
{
fprintf(stderr,"Usage: %s <UDP SERVER PORT>\n", argv[0]);
exit(1);
}
echoServPort = atoi(argv[1]); /* First arg: local port */
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 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(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("bind() failed");
for (;;) /* Run forever */
{
/* Set the size of the in-out parameter */
cliAddrLen = sizeof(echoClntAddr);
/* Block until receive message from a client */
if ((recvMsgSize = recvfrom(sock, echoBuffer, ECHOMAX, 0,
(struct sockaddr *) &echoClntAddr, &cliAddrLen)) < 0)
DieWithError("recvfrom() failed");
printf("Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr));
/* Parse string from client */
printf("echoBuffer Content: %s\n", echoBuffer);
hldType = strtok(echoBuffer, ".");
hldSend = strtok(NULL, ".");
hldRecip = strtok(NULL, ".");
hldMsg = strtok(NULL, ".");
printf("value of hldType: %s\n", hldType); /* Validated that it prints "0" */
/* Store message sent from client */
time_t now;
time(&now);
printf("%s", ctime(&now));
if (strcmp(hldType,REQTYPE) == 0) /* NOT WORKING */
printf("REQTYPE myString: %s\n", REQTYPE);
ServerMessage_new[0].messageType = atoi(hldType);
printf("hldType Content: %d\n", ServerMessage_new[0].messageType);
ServerMessage_new[0].SenderId = atoi(hldSend);
printf("hldSend Content: %04d\n", ServerMessage_new[0].SenderId);
ServerMessage_new[0].RecipientId = atoi(hldRecip);
printf("hldRecip Content: %04d\n", ServerMessage_new[0].RecipientId);
strncpy(ServerMessage_new[0].message, hldMsg, 40);
printf("hldMsg Content: %s\n", ServerMessage_new[0].message);
/* Send received datagram back to the client */
if (sendto(sock, echoBuffer, recvMsgSize, 0,
(struct sockaddr *) &echoClntAddr, sizeof(echoClntAddr)) != recvMsgSize)
DieWithError("sendto() sent a different number of bytes than expected");
}
/* NOT REACHED */
}
Try this:
printf( "comparing [%s] to [%s]\n", hldType, REQTYPE);
if (strcmp(hldType,REQTYPE) == 0) /* NOT WORKING */
printf("REQTYPE myString: %s\n", REQTYPE);
You may find extra whitespace in one of your strings. You can also print the return value from calling strcmp().
If hldType and REQTYPE are both "0", then strcmp() should be returning 0 (equal).
I think strtok isn't finding any parseable tokens. I mean, there's no "." in the input string. Check it.