I'm writing a simple client-server code in C.
i was asked for the server to print the IP address of the client that connected to it.
However, i can't seem to find a way to know the client's IP address from the server console.
Is there a way to do that?
// Initialize Winsock.
if ( StartupRes != NO_ERROR )
{
printf( "error %ld at WSAStartup( ), ending program.\n", WSAGetLastError() );
// Tell the user that we could not find a usable WinSock DLL.
return;
}
/* The WinSock DLL is acceptable. Proceed. */
// Create a socket.
MainSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( MainSocket == INVALID_SOCKET )
{
printf( "Error at socket( ): %ld\n", WSAGetLastError( ) );
return;
}
// Create a sockaddr_in object and set its values.
// Declare variables
Address = inet_addr(CHANNEL_IP);
if ( Address == INADDR_NONE )
{
printf("The string \"%s\" cannot be converted into an ip address. ending program.\n",
CHANNEL_IP);
return;
}
service.sin_family = AF_INET;
service.sin_addr.s_addr = Address;
service.sin_port = htons(clientinfo->senderPort);
//Bind the socket
bindRes = bind( MainSocket, ( SOCKADDR* ) &service, sizeof( service ) );
if ( bindRes == SOCKET_ERROR )
{
printf( "Channel-bind( ) failed with error %ld. Ending program\n", WSAGetLastError( ) );
return;
}
// Listen on the Socket.
ListenRes = listen( MainSocket, SOMAXCONN );
if ( ListenRes == SOCKET_ERROR )
{
printf( "Failed listening on socket, error %ld.\n", WSAGetLastError() );
return;
}
printf("Channel waiting for sender to connect...\n");
//Accepting connection
SenderSocket = accept( MainSocket, NULL, NULL );
if ( SenderSocket == INVALID_SOCKET ){
printf( "Accepting connection with client failed, error %ld\n", WSAGetLastError() ) ;
return;}
else
printf( "Sender Connected.\n" );
You need to pass in non-null values for the second and third parameters to accept:
struct sockaddr_in client_addr;
socklen_t slen = sizeof(client_addr);
SenderSocket = accept( MainSocket, (struct sockaddr *)&client_addr, &slen );
You can then get the client's IP and port from client_addr.
Related
I've just recently started playing around with sockets in C. Today I've been trying to write a server application to run on an old laptop of mine, just to experiment a bit.
I'd like for the server's services to be accessible from remote hosts and I'm confused about which IP address the server's socket should be bound to: is there an IP address that uniquely identifies my machine online or am I missing a step (or possibly many more) here?
struct sockaddr_in serverAddress;
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
serverAddress.sin_port = htons(8080);
if(bind(serverSocketDescriptor, (struct sockaddr*) &serverAddress, sizeof(serverAddress)) < 0) {
printf("bind() failed\n");
closesocket(serverSocketDescriptor);
WSACleanup();
return EXIT_FAILURE;
}
You want to bind to INADDR_ANY, which translates to 0.0.0.0.
serverAddress.sin_addr.s_addr = INADDR_ANY;
Binding to this address means the socket is bound to all local addresses, including localhost and any external IPs the host may have.
Suggest reading: server code sequence
// int socket(int domain, int type, int protocol);
sock_t sock = socket(AF_INET, SOCK_STREAM, 0);
if( sock < 0 )
{
perror( "socket failed" );
exit( EXIT_FAILURE );
}
// if wanting to set any socket options (setsockopt())
// this is the place to do so
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr( INADDR_ANY );
server.sin_port = htons(8080);
if( bind( sock, (struct sockaddr*) &server, sizeof(server) ) )
{
perror( "bind() failed" );
close( sock );
exit( EXIT_FAILURE );
}
if( listen(sock, 5) )
{
perror( "listen failed" );
exit( EXIT_FAILURE );
}
struct sockaddr_in client;
size_t len = sizeof( client );
while(1)
{
sock_t clientSock = accept(sock, &client, &len);
if( clientSock < 0 )
{
perror( "accept failed" );
continue;
}
// handle client connection
close( clientSock );
}
close( sock );
Note: for long term consistency, the computer running this code needs to have a 'static' IP address, not a 'dynamic' IP address.
I am new to the topic of network communication, but would like to set up an UDP server client connection, with one participant continuously broadcasting data whether anyone is listening in on it or not and two participants that start receiving and storing these information whenever they are ready to do so (It's fine if they miss what has been sent before that point). The idea is that there is no other communication than one participant sending data (fire and forget) and two participants receiving them, without any form of feedback to the sending part. For now I would like to get it running on my local host, but would like to use it on a network.
I have been looking into a solution for quite some time now and decided to have a client broadcast the file stream continuously on two separate ports so, so that the receiving two servers can bind to a port respectively without blocking each other (If there is a better way, I am open for suggestions).
So far I have been able to set up this kind of communication with one client and one server, following these instructions. However, when I try to set up a second socket in my client executable, I always receive the error message Invalid argument once I reach the sendto() part.
Seeing as I have not been able to find a solution myself, yet I would like to ask for some help.
My code so far consists of the
Client:
/** set up socket_1 properties */
struct addrinfo hints;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
/** Read address information of incoming connection */
int status;
struct addrinfo *servinfo;
if ((status = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
/** loop through all the results and bind to the first we can */
int sockfd;
struct addrinfo *p;
for ( p = servinfo; p != NULL; p = p->ai_next ) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
// /** Allow the reuse of a socket */
// if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int) ) == -1 ){
// printf("[ERROR]: Failed setting reusable socket %s.\n", strerror( errno ) );
// exit(1);
// }
// /** Allow the reuse of a socket */
// if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEPORT, &(int){ 1 }, sizeof(int) ) == -1 ){
// printf("[ERROR]: Failed setting reusable socket %s.\n", strerror( errno ) );
// exit(1);
// }
break;
}
if (p == NULL) {
printf("[ERROR]: Failed to bind broadcaster socket 1: %s.\n", strerror(errno) );
return 2;
}
/** set up socket_2 */
// ( reuse socket_1 hints and change the port number )
/** Read address information of incoming connection */
int status_2;
struct addrinfo *servinfo_2;
if ((status_2 = getaddrinfo(NULL, MYPORT_2, &hints, &servinfo_2)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status_2));
return 1;
}
/** loop through all the results and bind to the first we can */
int sockfd_2;
struct addrinfo *p_2;
for ( p_2 = servinfo_2; p_2 != NULL; p_2 = p_2->ai_next ) {
if ((sockfd_2 = socket(p_2->ai_family, p_2->ai_socktype, p_2->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
// /** Allow the reuse of a socket */
// if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int) ) == -1 ){
// printf("[ERROR]: Failed setting reusable socket %s.\n", strerror( errno ) );
// exit(1);
// }
// /** Allow the reuse of a socket */
// if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEPORT, &(int){ 1 }, sizeof(int) ) == -1 ){
// printf("[ERROR]: Failed setting reusable socket %s.\n", strerror( errno ) );
// exit(1);
// }
break;
}
if (p_2 == NULL) {
printf("[ERROR]: Failed to bind broadcaster socket 2: %s.\n", strerror(errno) );
return 2;
}
...
some file read/write related stuff
...
while ( /* some condition */ )
{
if ( ( readBytes = pread( fd, buf, BUFFER_SIZE, offset ) ) == -1 ){
printf("[ERROR]: %s.\n", strerror(errno) );
free( buf );
close( fd );
close( sockfd );
exit(1);
}
// the next line is generating the error message
if ( ( numbytes = sendto( sockfd, buf, readBytes, 0, p->ai_addr, p->ai_addrlen ) ) == -1 )
{
perror("sender_1: sendo.\n");
free( buf );
close( fd );
close( sockfd );
exit(1);
}
if ( ( numbytes = sendto( sockfd_2, buf, readBytes, 0, p_2->ai_addr, p_2->ai_addrlen ) ) == -1 )
{
perror("sender_2: sendo.\n");
free( buf );
close( fd );
close( sockfd_2 );
exit(1);
}
}
.
.
.
free( buf );
freeaddrinfo(servinfo);
freeaddrinfo(servinfo_2);
printf( "Broadcasting complete.\n" );
/** Clean what is not necessary anymore */
close( fd );
close( sockfd );
return 0;
}
I tried to add the reuse port and IP functionality to make sure that there is nothing blocking the setup of the new socket, but this did not solve my problem
My server side seems to work fine, but just in case I will post it here, too:
int main(int argc, char **argv)
{
if (argc < 2){
printf("Please provide image Name ID.\n");
exit(1);
}
struct addrinfo hints;
struct addrinfo *servinfo = NULL; // will point to getaddrinfo() results
memset(&hints, 0, sizeof hints); // make sure struct is empty
hints.ai_family = AF_UNSPEC; // don't care if IPv4 or IPv6
hints.ai_socktype = SOCK_DGRAM; // Use UDP protocol
hints.ai_flags = AI_PASSIVE;
int res;
if ((res = getaddrinfo( NULL, argv[1]/* SERVERPORT*/, &hints, &servinfo )) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(res));
return 1;
}
/** Get socket file descriptor */
int sockfd;
struct addrinfo *p = NULL;
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
/** Allow the reuse of an IP */
if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int) ) == -1 ){
printf("[ERROR]: Failed setting reusable socket %s.\n", strerror( errno ) );
exit(1);
}
/** Allow the reuse of a socket */
if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEPORT, &(int){ 1 }, sizeof(int) ) == -1 ){
printf("[ERROR]: Failed setting reusable socket %s.\n", strerror( errno ) );
exit(1);
}
/** Bind found socket to desired port */
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
printf("[ERROR]: Failed to bind socket to desired port: %s.\n", strerror( errno ) );
continue;
}
break;
}
struct timeval read_timeout;
read_timeout.tv_sec = 30;
read_timeout.tv_usec = 500;
if ( setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &read_timeout, sizeof read_timeout) < 0 ){
printf( "[ERROR]: %s.\n", strerror(errno) );
}
...
some file read/write stuff
...
while ( ( numbytes = recvfrom(sockfd, buf, BUFFER_SIZE, 0, (struct sockaddr *)&their_addr, &addr_len ) ) != -1)
{
.
.
.
}
printf("Done broadcasting.\n");
freeaddrinfo(servinfo);
close(sockfd);
return 0;
}
It would be much appreciated if anybody could provide me some help or point me into the right direction where to look for a solution.
Best regards
I'm writing a basic proxy server in C.
I want to identify the server/machine I am receiving the request from, by name or IP.
How does one do this? I'm not sure where to get the information from.
Here's my connection code:
unsigned short port = atoi(argv[1]); /* port number to listen on */
struct sockaddr_in server;
server.sin_family = PF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( port );
/* host-to-network-short() convert to big endian */
int len = sizeof( server );
if ( bind( sock, (struct sockaddr *)&server, len ) < 0 )
{
perror( "bind() failed" );
return EXIT_FAILURE;
}
/* activate the socket as a listener */
listen( sock, 5 ); /* 5 is number of backlogged waiting client requests */
//printf( "Listener socket created and bound to port %d on fd %d\n", port, sock );
struct sockaddr_in client;
while ( 1 )
{
// printf( "Blocked on accept()\n" );
unsigned int fromlen;
int newsock = accept( sock, (struct sockaddr *)&client, &fromlen );
/* accept() blocks */
//printf( "Accepted client connection\n" );
char buffer[5000];
int n = read( newsock, buffer, 4999 );
if ( n < 1 )
{
perror("Read() failed.\n");
}
else
{
buffer[n] = '\0';
//printf( "Rcvd message from client: \n\n----\n\n%s\n\n----\n\n", buffer );
}
Here is how you retrieve IP & hostname:
struct sockaddr_in client;
[...]
int newsock = accept( sock, (struct sockaddr *)&client, &fromlen );
printf("Client accepted: %s \n", inet_ntoa(client.sin_addr));
// And the host name
struct hostent *hostName;
struct in_addr ipv4addr;
inet_pton(AF_INET, inet_ntoa(client.sin_addr), &ipv4addr);
hostName = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET);
printf("Host name: %s\n", hostName->h_name);
I've got an assignment to write a server program that accepts multiple clients. I'm writing in C language and trying to accomplish this using a select() statement. I am able to compile, but whenever I telnet in, I get a "Socket operation on non-socket error." I've tried researching the error, but can't find anything too helpful. Any assistance would be appreciated.
The output of my server is:
$ ./assign2 33333
Waiting for connection...
fd is 0
EchoServ recv error: Socket operation on non-socket
fd is 1
EchoServ recv error: Socket operation on non-socket
EchoServ recv error: Socket operation on non-socket
The output of telnet is:
$ telnet localhost 33333
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
Welcome to EchoServ chat.
My server code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define PORT 50000
main( int argc, char *argv[] )
{
char buf[ BUFSIZ ], /* buffer for incoming data */
*endptr, /* for strtol() */
*message = "Welcome to EchoServ chat. \r\n"; /* welcome message */
int masterSocket, /* main listening socket for server */
newSocket, /* new sockets for connecting clients */
opt = 1, /* for port reuse code */
nBytes, /* # of incoming bytes */
addrlen;
int i,j; /* temp vars */
short int port; /* port number */
fd_set master; /* master file descriptor list */
fd_set temp_fds; /* temp file descriptor list for select() */
int fdmax; /* maximum file descriptor number */
struct sockaddr_in sin;
/* Get port number from the command line, or
set to default port if no arguments were supplied */
if ( argc == 2 ) {
port = strtol(argv[1], &endptr, 0);
if ( *endptr ) {
fprintf(stderr, "EchoServ: Invalid port number.\n");
exit(EXIT_FAILURE);
}
}
else {
port = PORT;
}
FD_ZERO(&master); /* clear the master and temp sets */
FD_ZERO(&temp_fds);
/* Get an internet domain socket */
if ( ( masterSocket = socket( AF_INET, SOCK_STREAM, 0) ) == -1 ) {
perror( "EchoServ socket error" );
exit( 1 );
}
/* Complete the socket structure */
memset( &sin, 0, sizeof(sin) );
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(port);
/* Bind the socket to the port number */
if ( bind( masterSocket, ( struct sockaddr *) &sin, sizeof( sin ) ) == -1) {
perror( "EchoServ bind failed" );
exit( 1 );
}
/* Allow port reuse */
if ( setsockopt( masterSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof( opt ) ) == -1 ) {
perror( "EchoServ setsockopt error" );
exit(1);
}
/* Listen for clients that want to connect. */
if ( listen( masterSocket, 5 ) == -1 ) {
perror( "EchoServ listen error" );
exit( 1 );
}
/* add masterSocket to the master set */
FD_SET(masterSocket, &master);
/* track largest file descriptor, starting with masterSocket */
fdmax = masterSocket;
/* Wait for a client connection, then accept it. */
puts ( "Waiting for connection..." );
while(1){
temp_fds = master; /* copy master set to temp set */
//addrlen = sizeof(sin);
/* wait for activity on a socket */
if (select(fdmax+1, &temp_fds, NULL, NULL, NULL) == -1) {
perror("EchoServ select error");
exit(1);
}
for ( i = 0; i <= fdmax; i++ ){
printf("fd is %d\n", i); /*debug*/
if ( FD_ISSET( i, &temp_fds ) ){ /* true if file descriptor is in set */
/* accept new connection */
if ( i == masterSocket ){
addrlen = sizeof( sin );
if ( (newSocket = accept( masterSocket, ( struct sockaddr *) &sin, &addrlen )) == -1 )
perror("EchoServ: accept error");
else {
printf("New connection accepted\n"); /*debug*/
FD_SET( newSocket, &master ); /* add new connection to master set */
if ( newSocket > fdmax ) /* update max descriptor */
fdmax = newSocket;
//print details of new connection
printf("New connection on %s:%d, socket fd is %d \n",
inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), newSocket );
//send new connection greeting message
if( send( newSocket, message, strlen( message ), 0) == -1 )
{
perror("EchoServ welcome message error");
}
puts("Welcome message sent successfully");
}
}
}
/* handle incoming data */
else{
if ( ( nBytes = recv( i, buf, sizeof( buf ), 0 ) ) <= 0 ){ /* error or closed connection */
if ( nBytes == 0 ) /* connection closed */
printf( "EchoServ: socket %d closed by client\n", i );
else /* recv error */
perror("EchoServ recv error");
close( i ); /* close socket */
FD_CLR( i, &master ); /* remove from master set */
}
else { /* got some data */
for( j = 0; j <= fdmax; j++ ){
if ( FD_ISSET( j, &master ) ){ /* send data to all sockets */
if( j != i && j != masterSocket ){ /* except self and masterSocket */
if ( send( j, buf, nBytes, 0) == -1)
perror("EchoServ send error");
}
}
}
}
}
}
}
return( 0 );
}
Thanks for helping.
So you test if (FD_ISSET(i, &temp_fds)) and on the else branch you attempt to recv on i. So basically you're only trying to receive if i is invalid or would block.
This all of course stems from the unbounded use of blocks and braces. You probably meant that else to be paired with if (i == masterSocket).
I'm writing a basic proxy server in C for class.
I'm testing with firefox, and I've got the server successfully receiving the browser's requests.
But now I need to send them out to the internet to get the pages the browser wants, and I'm hesitant.
Here is my present code for connecting.
I'm not sure if port 8080 is correct, and I'm not sure what to put for "gethostbyname".
That's the portion I was hoping to get some advice on.
int sock = socket( PF_INET, SOCK_STREAM, 0 );
if ( sock < 0 )
{
perror( "socket() failed" );
return EXIT_FAILURE;
}
struct sockaddr_in server;
struct hostent * hp;
server.sin_family = PF_INET;
hp = gethostbyname( "localhost" );
if ( hp == NULL )
{
perror( "Unknown host" );
return EXIT_FAILURE;
}
bcopy( (char *)hp->h_addr, (char *)&server.sin_addr, hp->h_length );
int port = 8080;
server.sin_port = htons( port );
if ( connect( sock, (struct sockaddr *)&server, sizeof( server ) ) < 0 )
{
perror( "connect() failed" );
return EXIT_FAILURE;
}
That entire gethostbyname, copying around (ha - even with the overly old bcopy)... just use getaddrinfo (extensive error checking left out for brevity):
int ret = getaddrinfo("localhost", "80" /* (or 8080, whichever applies) */, NULL, &res);
if (ret == 0) {
const struct addrinfo *r;
for (r = res; r != NULL || ret != 0; r = r->ai_next)
ret = connect(fd, res->ai_addr, res->ai_addrlen);
}
freeaddrinfo(res);