On linux I want to connect to a demon, via a socket in a compiled c.cgi program (cgic), which is listening for incoming socket connections. I know the server works because it will responded to 'nc' commands. Assume the server is black-boxed, I can't change it. In my client program I have:
int sockfd;
int len;
struct sockaddr_in address;
int result;
char ch[] = "get=DeviceNo";
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = 3042;
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *) &address, len);
Which returns with a "Connection Refused" error at this point. As a test I compiled the netcat into the .cgi program which does work:
system("echo '-r get=DeviceNo' | nc localhost 3042");
Am I missing something maybe how the socket class is handled within a .cgi? What should I do to try and get this socket to connect or what can I do to further troubleshoot my problem?
When working with sockaddr_in type, you need to know that both socket address sin_addr.s_addr and port sin_port must be in network byte order. Most likely your host is little-endian.
So you need to use inet_addr returns correct value, but for the socket address you need to use:
address.sin_port = htons(3042);
Related
I'm creating a client/server socket and I need to get the sockets server IP using the sockaddr_in function getsocketname(). However, I'm not sure how to do this since I'm unable to do something like
struct sockaddr_in servAddr;
int IP = servAddr.getsockname(sock, (struct sockaddr *) %servAddr,sizeof(servAddr));
I believe getsockname() is used for the client side, not server, and only once a connection has been made successfully using a socket to a server you defined.
To explain, a possible flow to connect a client to a server is:
Create a socketfd var, like 'sock' in your case
Open the socketfd var with a socket(...) call
Create your own variable to store the server details, let's say:
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr("0.0.0.0"); // replace with actual server IP
serverAddr.sin_port = htons(80); // replace with actual port
Connect sockfd to the server specified with serverAddr using a connect(...) call
Get the client side IP and port for this connection using a getsockname(...) call
getsockname(socketfd, (struct sockaddr *) &clientAddr, sizeof(clientAddr));
char buffer[INET_ADDRSTRLEN]; // stores the client side IP address
inet_ntop(AF_INET, &clientAddr.sin_addr, buffer, sizeof(buffer));
int port = (int) ntohs(clientAddr.sin_port); // stores the client side port
printf("IP address: %s\n", buffer);
printf("Port: %d\n", port);
My goal is making a TCP/IP connection in a sender <-> server -> receiver fashion.
I have a server, sender and receiver. The server initial part looks like:
int main(int argc, char *argv[]){
int welcomeSocket, senderSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
if (2 != argc) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
welcomeSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(atoi(argv[1]));
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//int len=20;
//char sbuffer[len];
//inet_ntop(AF_INET, &(serverAddr.sin_addr), sbuffer, len);
//printf("address:%s\n",sbuffer);
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Bind the address struct to the socket ----*/
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error\n");
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
senderSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
//~~~~Some more code~~~
}
however this sets up the server ip address as 0.0.0.0. I have no clue whether this is correct or not, but all until now I had manually set up the ip address as 127.0.1.1 which is what I get when I type hostname -i in the terminal.
So, currently I am having my sender connect to the same IP address, but since I am working all files in the same computer I don't know if it will work across other computers in the network with this weird ip address 0.0.0.0. Can someone clarify (and maybe help fix) this small issue to me? I have tried reading other solutions that try to explain the difference between 0.0.0.0 and 127.0.0.1 but I couldn't find anything related to the performance on the connection/communication between server and sender in a TCP/IP connection.
And then the IPv4 address is listed as 129.15.78.12 in my system settings, but then again, not sure which one should be used for the server or receiver.
The difference is that by using INADDR_ANY you bind the service to all interfaces, as explained in
http://man7.org/linux/man-pages/man7/ip.7.html
and
understanding INADDR_ANY for socket programming - c
Other than that, if you keep this config any computer trying to reach your server will connect if it uses a valid external IP address, like the one you mention you see in the system settings. Hope this clarifies your question.
I want to ask if there is a possibility and if there is how do I send broadcast from my UDP server to client and after that send back response from client to server.
I need to implement an application where server sends broadcast on a subnetwork and clients are supposed to receive that message somehow and in that way would get server address so that they could send some messages back to server.
I created a socket with specified server port say 2000 and set setsockopt to SO_BROADCAST and sent some message with sendto but my client hangs on recvfrom forever. Seems like it does not receive anything from server's broadcasting. How to fix this?
SERVER:
struct sockaddr_in addr;
int socketfd,t=1;
socketfd = socket(PF_INET,SOCK_DGRAM,0);
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons("2000");
addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
if (setsockopt(socketfd, SOL_SOCKET, SO_BROADCAST ,&t, sizeof(t)))
ERR("setsockopt");
if(bind(socketfd,(struct sockaddr*) &addr,sizeof(addr)) < 0)
ERR("bind");
char *buf = "HelloFromServer!";
if(sendto(socketfd, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr)) <= 0)
{
perror("something went wrong..");
return EXIT_FAILURE;
}
CLIENT:
struct sockaddr_in addr;
int socketfd,t=1;
socketfd = socket(PF_INET,SOCK_DGRAM,0);
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons("2000");
addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
if (setsockopt(socketfd, SOL_SOCKET, SO_BROADCAST ,&t, sizeof(t)))
ERR("setsockopt");
char data[12];
struct sockaddr_in serv_addr;
socklen_t size=sizeof(serv_addr);
recvfrom(fd, (char *)data, sizeof(char[12]), 0, &serv_addr, &size);
And my client hangs on this recvfrom... and therefore I cannot get serv_addr to be stored so that I could send some message back to the server
Clients are supposed to receive that message somehow and in that way would get server address so that they could send some messages back to server.
I believe there is a problem here: for the clients to receive the message broadcasted by the server, they must first have the server's address. The only time that a socket can receive data/communications from an unknown address is a server using listen() on a port which has port forwarding set up (courtesy of the router). Thus, unless the clients already have the server address, it seems the client receiving the data would be impossible, hence the hanging on recvfrom().
The error in both server and client is in
addr.sin_port = htons("2000");
htons() takes an integer, not a string. Write
addr.sin_port = htons(2000);
instead.
I want to get the IP address of the client who’s just connected into my server running WinSock2. I’m using C.
You could get the client's IP-address and port via the call to accept().
Just pass in the appropriate data into the last two parameters.
struct sockaddr_in sa = {0}; /* for TCP/IP */
socklen_t socklen = sizeof sa;
... = accept(..., (struct sockaddr *) &sa, &socklen);
For details please read here.
Have not done it myself, but take a look at getpeername. Looks like this is what you need.
This work for me on winsock2. No need of getpeername
SOCKET newConnection;
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen);
char *ip = inet_ntoa(addr.sin_addr);
printf("Accepted Connection from : %s", ip);
I have the following typical code in C under Linux to get UDP data:
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
mysock.sin_family = AF_INET;
mysock.sin_addr.s_addr = INADDR_ANY;
mysock.sin_port = my_port;
bind(sock, &mysock, sizeof(mysock);
recvfrom(sock, buf, PKTSZ, 0, &client, len);
All the above code works, but now I have a need to find out the sender's udp port, is there a structure or system call I can use to retrieve such info when I receive a udp packet ?
thanks
recvfrom(sock, buf, PKTSZ, 0, &client, len);
The senders socket address is stored in the client variable of your code. To access the senders port use sockaddr_in instead of sockaddr. Example:
sockaddr_in client;
int len = sizeof(client);
recvfrom(sock, buf, PKTSZ, 0, (struct sockaddr *)&client, (socklen_t *)&len);
int port = ntohs(client.sin_port);
References:
Beej's Guide to Network Programming and MSDN
recvfrom() is supposed to return that to you in the fifth argument (struct sockaddr*).
EDIT:
Use something like this
struct sockaddr_in client;
recvfrom(... (struct sockaddr*)&client ...);
client.sin_port should be the sender's port.
UDP sender port would be transient. I don't think you could use that for anything other than for reporting.
The fifth argument can be cast to struct sockaddr_in, and there sin_port is the remote port number.
Casting the client to sockaddr_in solves my problem.
Yes! Remember the ntohs() above all! It wasn't until I used the programmer's calculator that I realized it WAS stored as BigEndian 15B3, not the presumably ephemeral port B315!