self._socket = socket(AF_INET, SOCK_DGRAM, 0);
// create addr
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(0);
addr.sin_addr.s_addr = INADDR_ANY;
// bind socket
bind(self._socket, (struct sockaddr *)&addr, sizeof(addr));
printf("befor getsockname()->%d\n", ntohs(addr.sin_port));
socklen_t len = sizeof(addr);
getsockname(self._socket, (struct sockaddr *)&addr, &len); // if i comment this func, the last printf() will print 0; if not, it will print a real in use udp port(and it is correct!)
printf("after getsockname()->%d\n", ntohs(addr.sin_port));
So, is that when assign htons(0) to a port, the local socket must use getsockname() to assign a available port to itself? Or anything else?
I think this is maybe because i just bind 0 to sin_port which mean to assign a random port but has not assigned by system yet, so just call getsockname() to make system really assign a port.
So, is that when assign htons(0) to a port, the local socket must use getsockname() to assign a available port to itself? Or anything else?
No, you must use bind() to assign a port to the socket. getsockname() tells you what port was assigned if you specified zero.
The whole point of the getsockname function is to get the sockaddr for the local side of the socket. For IPv4 sockets, this is an object of type sockaddr_in and it contains both the IP address and port.
Related
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);
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 a C code snippet that listens on UDP socket for incomming messages (and it works fine):
uint32_t udp_port = 101010; // example port
int sock_udp = socket(AF_INET, SOCK_DGRAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(udp_port);
bind(sock_udp, (struct sockaddr*) &server_address, (socklen_t) sizeof(server_address));
char buffer[20];
struct sockaddr_in sender_address;
socklen_t sender_len = (socklen_t) sizeof(struct sockaddr_in);
ssize_t rcv_len = recvfrom(sock_udp, buffer, sizeof(buffer), 0, (struct sockaddr * ) &sender_address, &sender_len);
After it I have information on the sender in sender_address structure and I can check addres, port etc. My question is: can I use recv, recvfrom or other similar function to listen for datagrams coming from a certain host? In other words, is it possible to drop datagrams from other sources without reading them?
You can "filter" and receive datagrams from a specified single source if you connect(2) the datagram socket.
If the socket sockfd is of type SOCK_DGRAM then addr is the address to
which datagrams are sent by default, and the only address from which
datagrams are received.
The standard phrases it a little different:
For SOCK_DGRAM sockets, the peer address identifies where all
datagrams are sent on subsequent send() functions, and limits the
remote sender for subsequent recv() functions
I'm having trouble figuring this out - I'm working with sockets in C using this guide - http://binarii.com/files/papers/c_sockets.txt
I'm trying to automatically get my ip and port using:
server.sin_port = 0; /* bind() will choose a random port*/
server.sin_addr.s_addr = INADDR_ANY; /* puts server's IP automatically */
...
...
bind(int fd, struct sockaddr *my_addr,int addrlen); // Bind function
After a successful bind, how do I find out what IP and Port I'm actually assigned?
If it's a server socket, you should call listen() on your socket, and then getsockname() to find the port number on which it is listening:
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if (getsockname(sock, (struct sockaddr *)&sin, &len) == -1)
perror("getsockname");
else
printf("port number %d\n", ntohs(sin.sin_port));
As for the IP address, if you use INADDR_ANY then the server socket can accept connections to any of the machine's IP addresses and the server socket itself does not have a specific IP address. For example if your machine has two IP addresses then you might get two incoming connections on this server socket, each with a different local IP address. You can use getsockname() on the socket for a specific connection (which you get from accept()) in order to find out which local IP address is being used on that connection.
The comment in your code is wrong. INADDR_ANY doesn't put server's IP automatically'. It essentially puts 0.0.0.0, for the reasons explained in mark4o's answer.
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!