Hi i am programming a networking client in c and i am using the getsocketname function to return the IP and port of the socket i have created but for some reason the IP is always returned as 0.0.0.0 here is the code:
#include <stdio.h> //include standard input/output library
#include <stdlib.h> //include standard libraries
#include <string.h> //include string headers
#include <unistd.h> //add definitions for constansts and functions
#include <sys/types.h> // include definitions for different data types
#include <sys/socket.h> //include socket support
#include <netinet/in.h> //define internet protocol functions
#include <arpa/inet.h> //define internet protocol functions
#include "Practical.h" //include practical header file
int main(int argc, char *argv[]) {
char myIP[16];
unsigned int myPort;
struct sockaddr_in server_addr,myaddr;
if (argc < 3 || argc > 4) // Test for correct number of arguments
DieWithUserMessage("Parameter(s)",
"<Server Address> <Echo Word> [<Server Port>]");
char *servIP = argv[1]; // First arg: server IP address (dotted quad)
char *echoString = argv[2]; // Second arg: string to echo
// Third arg (optional): server port (numeric). 7 is well-known echo port
in_port_t servPort = (argc == 4) ? atoi(argv[3]) : 7; //21
// Create a reliable, stream socket using TCP //23
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//this block of code creates a reliable tcp stream socket and checks what the returned integer is from the socket function, the returned function will give a integer that descibes the socket. if this is 0 then kill the socket and show the user an error message.
if (sock < 0)
DieWithSystemMessage("socket() failed"); //26
// Construct the server address structure //28
struct sockaddr_in servAddr; // Server address
memset(&servAddr, 0, sizeof(servAddr)); // Zero out structure
servAddr.sin_family = AF_INET; // IPv4 address family
// Convert address
int rtnVal = inet_pton(AF_INET, servIP, &servAddr.sin_addr.s_addr);
if (rtnVal == 0)
DieWithUserMessage("inet_pton() failed", "invalid address string");
else if (rtnVal < 0)
DieWithSystemMessage("inet_pton() failed");
servAddr.sin_port = htons(servPort); // Server port
myaddr.sin_addr.s_addr = INADDR_LOOPBACK;
bzero(&myaddr,sizeof(myaddr));
int len = sizeof(myaddr);
getsockname(sock,(struct sockaddr *) &myaddr, &len);
inet_ntop(AF_INET, &myaddr.sin_addr, myIP, sizeof(myIP));
myPort = ntohs(myaddr.sin_port);
printf("local ip address : %s\n", myIP);
printf("local port: %u\n", myPort);
// Establish the connection to the echo server
if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
DieWithSystemMessage("connect() failed");
size_t echoStringLen = strlen(echoString); // Determine input length //44
// Send the string to the server
ssize_t numBytes = send(sock, echoString, echoStringLen, 0);
if (numBytes < 0) //sending string to server, number of bytes of the message is equal to return value of send function, if the number of bytes is less than 0 then do not send and say to user that the send failed
DieWithSystemMessage("send() failed");
else if (numBytes != echoStringLen)
DieWithUserMessage("send()", "sent unexpected number of bytes"); //51
// if the number of bytes is not equal to the input length of the string parsed as an argument then die with the message to the user saying sent unexpected number of bytes.
// Receive the same string back from the server //53
unsigned int totalBytesRcvd = 0; // Count of total bytes received
fputs("Received: ", stdout); // Setup to print the echoed string
while (totalBytesRcvd < echoStringLen) {
char buffer[BUFSIZE]; // I/O buffer
/* Receive up to the buffer size (minus 1 to leave space for
a null terminator) bytes from the sender */
numBytes = recv(sock, buffer, BUFSIZE - 1, 0);
if (numBytes < 0)
DieWithSystemMessage("recv() failed");
else if (numBytes == 0)
DieWithUserMessage("recv()", "connection closed prematurely");
totalBytesRcvd += numBytes; // Keep tally of total bytes
buffer[numBytes] = '\0'; // Terminate the string!
fputs(buffer, stdout); // Print the echo buffer
}
fputc('\n', stdout); // Print a final linefeed //70
close(sock);
exit(0);
}
//closing off connections to clean up data left over.
the port number returned is always 0 too, i am assigning the address of the myaddr struct to be loopback address so i believe it is supposed to return 127.0.0.1 as the IP but it isn't, i am sort of new to socket programming so my logic might not be perfect, i just cant see whats wrong here
It means that the socket hasn't been bound to a local address yet.
You need to get the local address after it has been bound, which happens automatically with the connect call.
Related
So, I am working on an remote ls assignment in which we have to use TCP socket connection between two remote computers and run client.c on one side and server.c on another. Client program enters command; for e.g: ls
the server will parse it and returns the current working directory to client.
Note that I am running both programs on VM Workstation. One side is Ubuntu and another is Red Hat 6.
Issue: My client program couldn't connect to the server and its connect() function is returning -1.
I have tried to debug my program and so I am attaching the results:debug result
Note: I have hardcoded IP address and port no for the sake of debugging.
Here are the codes:
Client side:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include<netdb.h>
#include <string.h>
#include<unistd.h>
/*
Client side socket flow
socket()
|
|
v
connect()
|
|
v
recv()
*/
int main(int argc, char *argv[]) {
struct hostent *server;
struct sockaddr_in server_address;
int port_num;
int communication_status;
//create a socket
int network_socket;
//We will use 3 args while running client code.
/*
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
}*/
/*
socket(arg1,arg2,arg3)
- First arg: (AF_INET) = domain .. from IPV4 domain
- Sec arg: SOCK_STREAM - TCP Stream/Connection-Oriented
- Third arg: defines protocol - 0 for TCP <You can use RAW SOCKET HERE (SOCKETS WITH NO PROTOCOL)
*/
network_socket = socket(AF_INET,SOCK_STREAM,0);
/*
- So we can pass port no as int
- But data format is different from structure that we need to use a conversion function
- conversion function thats going to put our integer
port in right byte order is htons(agr = actual int port number we want to connect to)
*/
//define port you need to conenct remotely
port_num = 20102;
server_address.sin_port = htons(port_num);
//define server address
/*
-sin addr is field that contains structure itself
- we can use any address -- use shortcut ip.0.0.0 (INADDR_ANY)
*
/*
-now we need to use connect() to connect to other socket
- BUT FIRST WE NEED TO SPECIFY AN ADDRESS FOR SOCKET i.e. addr and port no
*/
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("192.168.177.128");
//now time to connect
/*
connect()
arg1: socket
arg2: need to cast our server addfress structure to slightly different struct
from sockaddr_in to sockaddr*
arg3: sizeof the address
connect() returns integer
0 - successful connection
-1 - not successfull
*/
int connection_status;
connection_status = connect(network_socket,(struct sockaddr *) &server_address,sizeof(server_address));
//check for error with the connection
if (connection_status == -1) {
printf("There was an error making a connection to the remote socket \n\n");
}
// recieve data from the server
/*
- recv() function
- first arg: socket
- 2nd arg: address of var where data recived will end up (here it is char array)
- 3rd arg: optional flag parameter give 0
*/
//string to hold data exchanged between client and server
char buffer[256];
printf("Please enter the linux command: ");
//clears the buffer content
bzero(buffer,256);
//get linux command from the console
fgets(buffer,255,stdin);
communication_status = write(network_socket,buffer,strlen(buffer));
//check for write status
if (communication_status < 0) {
perror("Error writing to socket!");
exit(1);
}
//Now getting server response
//clear the buffer
bzero(buffer,256);
communication_status = read(network_socket,buffer,255);
if (communication_status < 0) {
perror("Error reading from socket!");
exit(1);
}
//now we have to print the server response
printf("Server>>: %s\n", buffer);
//close the socket
close(network_socket);
return 0;
}
Server side:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include <stdlib.h>
#include <string.h>
#include<unistd.h>
int readAndParseCmdLine(char **, char **);
int main(int argc, char *argv[]) {
//Checks if the num of argument is 2, if not error message is displayed.
if(argc<2) {
fprintf(stderr,"Num of argument Error");
}
//buffer for data exchange
char buffer[256];
int clientlength, portnum, newSocket;
struct sockaddr_in server_address, cli_addr;
int communication_status,newsockfd;
//create server
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM,0);
if(server_socket == -1) {
perror("Could not connect to socket");
exit(1);
}
//define the server address
bzero((char *) &server_address, sizeof(server_address));
//Coverts the character value to integer for the portno
portnum = atoi(argv[1]);
server_address.sin_family = AF_INET;
server_address.sin_port = htons(portnum);
server_address.sin_addr.s_addr = INADDR_ANY;
//bind the socket to our specified IP and port
//bind is used exactly like we call the connection()
//OS gives resources like port number to Server through bind()
if ( bind(server_socket,(struct sockaddr*) &server_address,sizeof(server_address)) < 0 ) {
perror("Can't bind");
exit(1);
}
/*
listen()
first arg: socket
second arg: backlog (how many connection can be waiting -
essentially for this particular socket at a time - since
we are using this for one client, we can use any number)
*/
listen(server_socket,5);
clientlength = sizeof(cli_addr);
/*
define integer to hold client's socket as once we able to listen() connection
and we can actually start accepting() connections so we can read or write to
clients socket
*/
//The new socket for the client informations
/*
if(newsockfd<1)
{
sleep(1);
}
*/
newSocket = accept(server_socket,(struct sockaddr *) &cli_addr, &clientlength);
if (newSocket < 0) {
perror("ERROR on accept");
exit(1);
}
//Clears the buffer
bzero(buffer,256);
communication_status = read(newSocket,buffer,255);
if (communication_status < 0) {
perror("ERROR reading from socket");
exit(1);
}
//Buffer Stores the msg sent by the client
printf("Here is the entered bash command: %s\n",buffer);
communication_status = write(newSocket,"I got your message",18);
if (communication_status < 0)
{
error("ERROR writing to socket");
}
char *prog;
strcpy(prog, buffer);
char *args[100];
int child_pid;
//Running the Bash Commands
if(readAndParseCmdLine(&prog, args)) {
child_pid =fork();
if(child_pid == 0){ //child part
printf("\n");
execvp(prog, args); // create and run the new process and close the child process
printf("\n");
prog = NULL;
printf("Error in excuting the command- please make sure you type the right syntax.\n");
} else{ //parent part
wait(child_pid);
}
void main();
}
}
//This function reads the linux command form the buffer and parse it
//
int readAndParseCmdLine(char **prog, char **args){
int i =0;
char cmd[100]; //user command
char * temp;
temp = *prog;
if(strcmp(temp,"exit")==0){return 0;} //end program if user type exit.
char *tok;
tok = strtok(temp," \n");
while(tok != NULL){
if(i==0){
prog[0] = tok;
}
args[i] = tok;
printf("\n");
i=i+1;
tok = strtok(NULL, " \n");
}
args[i]=NULL;
return 1;
}
Both programs compile, and I'm able to successfully create a socket, but the connection to the server fails. This is basically a TCP echo program.
PS. I'm new here so IDK how to use this, I don't have much programming experience so bare with me.
tcp echo client-1
tcp echo client-2
tcp echo server-1
tcp echo server-2
Compiling/Running server gives me: Server not fully implemented...
Compiling/Running client gives me: Socket successfully created..Error: connection to the server failed!
**// TCP echo client program**
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main (int argc, char* argv[ ]) // Three arguments to be checked later
{
struct sockaddr_in servAddr; // Server socket address data structure
char *servIP = argv[1]; // Server IP address from command line
int servPort = atoi(argv[2]); // Server port number from command line
char *message = argv[3]; // Message specified on the command line
char buffer [512 + 1];
char* ptr = buffer;
int len;
int max_len = sizeof(buffer);
int sock_descrip;
// Check for correct number of command line arguments
if(argc != 4) {
printf("tcp-echo-client [IP address] [Port] [Message]\n");
exit (1);
}
// Populate socket address for the server
memset (&servAddr, 0, sizeof(servAddr)); // Initialize data structure
servAddr.sin_family = AF_INET; // This is an IPv4 address
servAddr.sin_addr.s_addr = inet_addr(servIP); // Server IP address
servAddr.sin_port = servPort; // Server port number
// Create a TCP socket stream
int sock;
if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
printf("Error: socket creation failed!\n");
exit (1);
}
else
printf("Socket successfully created..\n");
// Connect to the server
if ((connect (sock, (struct sockaddr*)&servAddr, sizeof(servAddr))) == -1) {
printf("Error: connection to the server failed!\n");
exit (1);
}
else
printf("Connected to the server..\n");
// Send data to the server...
send(sock_descrip, message, strlen(message),0);
int x;
while ((x = recv(sock_descrip, ptr, max_len,0))>0)
{
ptr += x;
max_len -= x;
len += x;
}
buffer[len] = '\0';
printf("Echoed string received: %s %c", buffer,*message);
// Receive data back from the server..
// Loop while receiving data...
// print data...
// end-while loop
// Close socket
close (sock);
// Stop program
exit (0);
} // End main
**//TCP Echo server program**
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFLEN 512 // Maximum length of buffer
#define PORT 9988 // Fixed server port number
int main (void)
{
struct sockaddr_in server_address; // Data structure for server address
struct sockaddr_in client_address; // Data structure for client address
int client_address_len = 0;
char buffer [512];
char* ptr = buffer;
int len;
int max_len = BUFLEN;
int sock_descrip;
// Populate socket address for the server
memset (&server_address, 0, sizeof (server_address)); // Initialize server address data structure
server_address.sin_family = AF_INET; // Populate family field - IPV4 protocol
server_address.sin_port = PORT; // Set port number
server_address.sin_addr.s_addr = INADDR_ANY; // Set IP address to IPv4 value for loacalhost
// Create a TCP socket; returns -1 on failure
int listen_sock;
if ((listen_sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
printf("Error: Listen socket failed!\n");
exit (1);
}
// Bind the socket to the server address; returns -1 on failure
if ((bind(listen_sock, (struct sockaddr *)&server_address, sizeof (server_address))) == -1) {
printf("Error: binding failed!\n");
exit (1);
}
printf("Server not fully implemented...\n");
// Listen for connections...
int wait_size;
if (listen(listen_sock, wait_size) == -1)
{
printf("Error: listening failed!\n");
exit(1);
}
for(;;)
{
if(sock_descrip=accept(listen_sock,(struct sockaddr *)&client_address, &client_address_len) == -1)
{
printf("Error: accepting failed!\n");
exit(1);
}
int x;
while ((x = recv(sock_descrip, ptr, max_len, 0)) > 0)
{
ptr += x;
max_len -= x;
len += x;
}
send(sock_descrip,buffer,len,0);
}
// Echo data back to the client...
close (listen_sock); // Close descriptor referencing server socket
} // End main
You need parentheses around the assignment:
if(
(sock_descrip=accept(listen_sock,(struct sockaddr *)&client_address, &client_address_len))
== -1)
i have a server/client application and i am trying to get the server to read each message the client sends to it and send it back to the client to be printed. so far i have the server reading the first message and sending that to the client and that prints fine, but when the second message is sent from the client, i try to print it from the HandleTcpClient function to test it and it just prints null, i am not sure if it is receiving it correctly
client code:
#include <stdio.h> //include standard input/output library
#include <stdlib.h> //include standard libraries
#include <string.h> //include string headers
#include <unistd.h> //add definitions for constansts and functions
#include <sys/types.h> // include definitions for different data types
#include <sys/socket.h> //include socket support
#include <netinet/in.h> //define internet protocol functions
#include <arpa/inet.h> //define internet protocol functions
#include "Practical.h" //include practical header file
int main(int argc, char *argv[]) {
char myIP[16];
unsigned int myPort;
struct sockaddr_in server_addr,myaddr;
char username[] = "CharlieA";
if (argc < 2 || argc > 3) // Test for correct number of arguments
DieWithUserMessage("Parameter(s)",
"<Server Address> [<Server Port>]");
char *servIP = argv[1]; // First arg: server IP address (dotted quad)
// Third arg (optional): server port (numeric). 7 is well-known echo port
in_port_t servPort = atoi(argv[2]); //21
printf("serv port: %d\n",servPort);
// Create a reliable, stream socket using TCP //23
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//this block of code creates a reliable tcp stream socket and checks what the returned integer is from the socket function, the returned function will give a integer that descibes the socket. if this is 0 then kill the socket and show the user an error message.
if (sock < 0)
DieWithSystemMessage("socket() failed"); //26
// Construct the server address structure //28
struct sockaddr_in servAddr; // Server address
memset(&servAddr, 0, sizeof(servAddr)); // Zero out structure
servAddr.sin_family = AF_INET; // IPv4 address family
// Convert address
int rtnVal = inet_pton(AF_INET, servIP, &servAddr.sin_addr.s_addr);
if (rtnVal == 0)
DieWithUserMessage("inet_pton() failed", "invalid address string");
else if (rtnVal < 0)
DieWithSystemMessage("inet_pton() failed");
servAddr.sin_port = htons(servPort); // Server port
myaddr.sin_addr.s_addr = INADDR_ANY;
// Establish the connection to the echo server
if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
DieWithSystemMessage("connect() failed");
//get address of bound socket after connect function call (binds automatically with connect method)
bzero(&myaddr,sizeof(myaddr));
int len = sizeof(myaddr);
getsockname(sock,(struct sockaddr *) &myaddr, &len);
inet_ntop(AF_INET, &myaddr.sin_addr, myIP, sizeof(myIP)); //convert network address to string
myPort = ntohs(myaddr.sin_port); //convert from netshort to hostbyte order
//getlocal ip address to be sent to server
char *echoString=(char*)malloc(13*sizeof(char));
sprintf(echoString,"netsrv type0 %s %s-%u\r\n",username,myIP,myPort); //generate request string
size_t echoStringLen = strlen(echoString); // Determine input length //44
size_t iplen = strlen(myIP);
// Send the string to the server
ssize_t numBytes = send(sock,echoString, echoStringLen, 0);
printf("sent: %s", echoString);
if (numBytes < 0) //sending string to server, number of bytes of the message is equal to return value of send function, if the number of bytes is less than 0 then do not send and say to user that the send failed
DieWithSystemMessage("send() failed");
else if (numBytes != echoStringLen)
DieWithUserMessage("send()", "sent unexpected number of bytes"); //51
// if the number of bytes is not equal to the input length of the string parsed as an argument then die with the message to the user saying sent unexpected number of bytes.
//send IP to server
send(sock,myIP,iplen,0); //send client IP
// Receive the same string back from the server //53
unsigned int totalBytesRcvd = 0; // Count of total bytes received
while (totalBytesRcvd < echoStringLen) {
char buffer[BUFSIZE]; // I/O buffer
/* Receive up to the buffer size (minus 1 to leave space for
a null terminator) bytes from the sender */
numBytes = recv(sock, buffer, BUFSIZE - 1, 0);
if (numBytes < 0)
DieWithSystemMessage("recv() failed");
else if (numBytes == 0)
DieWithUserMessage("recv()", "connection closed prematurely");
totalBytesRcvd += numBytes; // Keep tally of total bytes
buffer[numBytes] = '\0'; // Terminate the string!
fputs("Received: ", stdout); // Setup to print the echoed string
fputs(buffer, stdout); // Print the echo buffer
}
fputc('\n', stdout); // Print a final linefeed //70
close(sock);
exit(0);
}
//closing off connections to clean up data left over.
The second message is the send client IP commented line
Server:
#include <stdio.h> //include standard input/output library
#include <stdlib.h> //include standard libraries
#include <string.h> //include string headers
#include <sys/types.h> //add definitions for constansts and functions
#include <sys/socket.h> // include definitions for different data types
#include <netinet/in.h> //define internet protocol functions
#include <arpa/inet.h> //define internet protocol functions
#include "Practical.h" //include pactical
static const int MAXPENDING = 5; // Maximum outstanding connection requests
static const int servPort = 48031;
int main(int argc) {//run on command line = "echoSvr <port>";argc = 2 command and parameter- argv[0] = echoSvr and argv[1] = <port>
// Create socket for incoming connections
int servSock; // Socket descriptor for server
if ((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithSystemMessage("socket() failed");
// this block of code is creating a socket stream to accept the incoming connections from clients
// Construct local address structure
struct sockaddr_in servAddr; // Local address; internet socket address structure
memset(&servAddr, 0, sizeof(servAddr)); // Zero out structure
servAddr.sin_family = AF_INET; // IPv4 address family
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface; host to network long[integer]
servAddr.sin_port = htons(servPort); // Local port; host to network short[integer]
// Bind to the local address
if (bind(servSock, (struct sockaddr*) &servAddr, sizeof(servAddr)) < 0)//cast servaddr as generic socket address structure
DieWithSystemMessage("bind() failed");
// Mark the socket so it will listen for incoming connections
if (listen(servSock, MAXPENDING) < 0)
DieWithSystemMessage("listen() failed");
setvbuf (stdout, NULL, _IONBF, 0);
printf("Listening on port: %d \n" , servPort);
printf("awaiting connection from client.... \n");
// this block of code binds the socket to the address of the server and tells the binded to socket to begin listening in for connections coming from client machines
for (;;) { // Run forever
struct sockaddr_in clntAddr; // Client address
// Set length of client address structure (in-out parameter)
socklen_t clntAddrLen = sizeof(clntAddr);
// Wait for a client to connect
int clntSock = accept(servSock, (struct sockaddr *) &clntAddr, &clntAddrLen);
if (clntSock < 0)
DieWithSystemMessage("accept() failed");
//this block of code waits for a client to connect to the socket and then accepts the connection from the client and prints the clients details out to screen
// clntSock is connected to a client!
char clntName[INET_ADDRSTRLEN]; // String to contain client address
if (inet_ntop(AF_INET, &clntAddr.sin_addr.s_addr, clntName,
sizeof(clntName)) != NULL)
printf("Handling client %s/%d\n", clntName, ntohs(clntAddr.sin_port));
else
puts("Unable to get client address");
HandleTCPClient(clntSock);
}
}
HandleTCPClient Function:
void HandleTCPClient(int clntSocket) {
char buffer[BUFSIZE]; // Buffer for echo string
char *clientIP;
unsigned int clientPort;
// Receive message from client
ssize_t numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
if (numBytesRcvd < 0)
DieWithSystemMessage("recv() failed");
//get ip and port of clntSocket to apply to greeting string
// Send greeting string and receive again until end of stream
while (numBytesRcvd > 0) { // 0 indicates end of stream
// Echo message back to client
ssize_t numBytesSent = send(clntSocket, buffer, numBytesRcvd, 0);
if (numBytesSent < 0)
DieWithSystemMessage("send() failed");
else if (numBytesSent != numBytesRcvd)
DieWithUserMessage("send()", "sent unexpected number of bytes");
// See if there is more data to receive
numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
if (numBytesRcvd < 0)
DieWithSystemMessage("recv() failed");
//recv client ip and assign to variable to hold
recv(clntSocket,clientIP,100,0);
printf("clientIP : %s" ,clientIP);
}
close(clntSocket); // Close client socket
}
i am trying to print the clientIP with the printf function and this is where i am getting a null, it just does not seem to be receiving it, there is a lot of code here, i am posting it all in case it is needed
That is a lot of code, so I didn't look at most of it. I did, however, notice:
char *echoString=(char*)malloc(13*sizeof(char));
sprintf(echoString,"netsrv type0 %s %s-%u\r\n",username,myIP,myPort);
Nowhere do you explain where that 13 comes from, but it is clearly not enough to hold the formatted string which sprintf will produce. It's enough to hold a 12-character string (plus the NUL terminator) which gets you up to netsrv type0. That needs to be fixed, since the sprintf will clobber random memory which doesn't belong to it, but that's probably not your immediate problem. (Use snprintf. Even simpler, if you're using Linux/OSX/FreeBSD, is asprintf.)
What I think might be your problem is this:
numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
//recv client ip and assign to variable to hold
recv(clntSocket,clientIP,100,0);
printf("clientIP : %s" ,clientIP);
You never look at the data received by the first recv() call. Perhaps you are under the misapprehension that each send somehow marks the data being sent so that recv will only read exactly the data sent by one send. That's not the case. TCP is a streaming protocol; the data is just an undistinguished series of bytes and each recv() receives whatever is available, subject to the size limit in the call. So it is quite possible that the result of both send() calls will show up in the first recv() call.
I think this is probably explained in whatever text/tutorial/guide you are using to write that code, but if not I strongly recommend finding a copy of W. R. Stevens' Unix Network Programming.
In short: If you want to send "messages", you need to figure out how to delimit them in a way that the receiver can tell where one message ends and the next one begins. A really simple strategy, used by many older internet protocols, is to end each message with a newline sequence and ensure that there are no newlines in any message.
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'm trying to send a modified string over sockets. The goal is to take a string from the client, add something to it, then send it back. The strings are passed in command line arguments. Right now, I can receive the message from the client, but for some reason my recvfrom function is returning -1 which causes the client to get hung up and not receive the sendto from the server. It seems like the server is modifying the string fine, but I can't get it to receive correctly on the other side. I have print statements in my code for testing purposes. The command line arguments for the client are server name, port number, string. The command line arguments for the server are port number, string to concatenate. Below is my code:
headerFiles.h:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/wait.h>
server.c:
#include "headerFiles.h"
int main(int argc, char* argv[])
{
int s;
int len;
char buffer[256];
struct sockaddr_in servAddr;
struct sockaddr_in clntAddr;
int clntAddrLen;
int serverPort;
char catStringMeow[256];
serverPort = atoi(argv[1]);
strcpy(catStringMeow, argv[2]);
// Build local (server) socket address
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(serverPort);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// Create socket
if((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Error: socket failed!");
exit(1);
}
// Bind socket to local address and port
if((bind(s, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0))
{
perror("Error: bind failed!");
exit(1);
}
for(;;) // Runs forever
{
printf("buffer = %s\n", buffer);
printf("In for\n");
// Receive String
len = recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr*)&clntAddr, &clntAddrLen);
printf("Received %d bytes\n", len);
printf("buffer = %s\n", buffer);
strcat(buffer, " ");
strcat(buffer, catStringMeow);
printf("New string = %s\n",buffer);
printf("buffer size = %d\n", (int)strlen(buffer));
len = (int)strlen(buffer);
// Send String
sendto(s, buffer, len, 0, (struct sockaddr*)&clntAddr, sizeof(clntAddr));
printf("Sent %d bytes\n", len);
}
}
client.c:
#include "headerFiles.h"
int main (int argc, char* argv[]) // Three arguments to be checked later
{
int s; // Socket descriptor
int len; // Length of string to be echoed
char* servName; // Server name
int servPort; // Server port
char* string; // String to be echoed
char buffer[256+1]; // Data buffer
struct sockaddr_in servAddr; // Server socket address
// Check and set program arguments
if(argc != 4)
{
printf("Error: three arguments are needed!\n");
exit(1);
}
servName = argv[1];
servPort = atoi(argv[2]);
string = argv[3];
// Build server socket address
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
inet_pton(AF_INET, servName, &servAddr.sin_addr);
servAddr.sin_port = htons(servPort);
// Create socket
if((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Error: Socket failed!");
exit(1);
}
// Send echo string
len = sendto(s, string, strlen(string), 0, (struct sockaddr*) &servAddr, sizeof(servAddr));
printf("Sent %d bytes\n", len);
// Receive echo string
len = recvfrom(s, buffer, len, 0, NULL, NULL);
printf("Received\n");
//Print and verify echoed string
buffer[len] = '\0';
printf("Echo string received: ");
fputs(buffer, stdout);
printf("\n");
// Close the socket
close(s);
// Stop the program
exit(0);
}
do
// Receive echo string
len = recvfrom(s, buffer, sizeof(buffer), 0, NULL, NULL);
printf("Received\n");
and make buffer bigger.
You're passing an uninitizlied clntAddrLen value to recvfrom, which is resulting in the Invalid argument error code. According to the documentation:
The argument addrlen is a value-result argument, which the caller should initialize before the call to the size of the buffer associated with src_addr, and modified on return to indicate the actual size of the source address.
So you need to initialize it with:
clntAddrLen = sizeof(clntAddr);
Make sure you initialize the client address length variable before using it in sendto or recvfrom.
The problem is that on the first calling to sendto from client.c, the servers sees the client's ip as 0.0.0.0, after that on the second, third,... calls the client.c get an ip and have a legal ip such as 127.0.0.3:3212.
You can see that second, third, ... clients work.
Initialize length variable to sizeof(struct sockaddr_in)