c udp socket not receiving/sending correctly - c++

I am currently experiencing some trouble while testing UDP sockets.
So I have 2 c programs, one sends and receives, the other receives and sends a message.
Here is send_recv.c:
#define PORT 1010
int main(int argc, const char *argv[]) {
int socketInfo, opt;
struct sockaddr_in server;
char msgOut[30], msgIn[30];
opt = 1;
printf("Input message: ");
fgets(msgOut, 30, stdin);
socketInfo = socket(AF_INET, SOCK_DGRAM, 0);
if(socketInfo < 0) {
perror("socket error");
return EXIT_FAILURE;
}
if(setsockopt(socketInfo, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt failed");
return EXIT_FAILURE;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
if(bind(socketInfo, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("bind error");
return EXIT_FAILURE;
}
if(connect(socketInfo, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("connection error");
return EXIT_FAILURE;
}
puts("connected");
send(socketInfo, msgOut, strlen(msgOut), 0);
puts("sleeping for 5");
sleep(5);
puts("message sent");
recv(socketInfo, msgIn, sizeof(msgIn), 0);
printf("received msg: %s\n", msgIn);
close(socketInfo);
return EXIT_SUCCESS;
}
And here is recv_send.c:
#define PORT 1010
int main(int argc, const char *argv[]) {
int socketInfo, opt;
struct sockaddr_in server;
char msgOut[30], msgIn[30];
opt = 1;
socketInfo = socket(AF_INET, SOCK_DGRAM, 0);
if(socketInfo < 0) {
perror("socket error");
return EXIT_FAILURE;
}
if(setsockopt(socketInfo, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt failed");
return EXIT_FAILURE;
}
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;
if(bind(socketInfo, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("bind error");
return EXIT_FAILURE;
}
if(connect(socketInfo, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("connection error");
return EXIT_FAILURE;
}
puts("connected");
recv(socketInfo, msgIn, sizeof(msgIn), 0);
printf("received msg: %s\n", msgIn);
printf("Input message: ");
fgets(msgOut, 30, stdin);
send(socketInfo, msgOut, strlen(msgOut), 0);
puts("message sent");
close(socketInfo);
return EXIT_SUCCESS;
}
The problem is that the receive program never receives anything, and the send program sends and then just receives the message it already received.
The output of send_rcv is this:
Input message: hello there
connected
message sent
received msg: hello there
and the output of rcv_send is this:
connected
(ctrl+z) Job 6, 'sudo ./rcv_send' has stopped
Another problem is that when I don't run the program with sudo it just says this: bind error: Permission denied

The problem is that both endpoints are listening on the same port while running on the same machine, and you have both sides sending to INADDR_ANY.
Also, port numbers below 1024 are privileged ports and therefore require root access to bind to.
Use a different port (1024 or higher) for each side of the connection, and choose a specific IP address to connect to. For example:
#define LOCAL_PORT 1100
#define REMOTE_PORT 1101
...
struct sockaddr_in local, remote;
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = htons(LOCAL_PORT);
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
remote.sin_port = htons(LOCAL_PORT);
if(bind(socketInfo, (struct sockaddr *)&local, sizeof(local)) < 0) {
perror("bind error");
return EXIT_FAILURE;
}
if(connect(socketInfo, (struct sockaddr *)&remote, sizeof(remote)) < 0) {
perror("connection error");
return EXIT_FAILURE;
}
The values of LOCAL_PORT and REMOTE_PORT would be swapped in the two programs.
Note also that you can get rid of the setsockopt call as you don't have two programs open on the same port.

Related

Why can't my client connect to the server?

I try to make a application that client send a message and the server respond on the same machine using winsock TCP c++. The problem is that after the server waited for client to connect, I ran the client code and it stopped at the connect and exit. This is my code.
Server:
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <iostream>
#define MY_PORT 8888
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//Init Winsock
WSADATA SData;
if (WSAStartup(0x0202, &SData) != 0)
{
cout << "KHONG THE KHOI DONG WINSOCK";
return 1;
}
//Init Socket
int listeningSocket;
if ((listeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
perror("socket failed");
WSACleanup();
exit(EXIT_FAILURE);
}
//Set IP and PORT
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(MY_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
//Bind
if (bind(listeningSocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("bind failed");
closesocket(listeningSocket);
WSACleanup();
exit(EXIT_FAILURE);
}
//Listen
if (listen(listeningSocket, 5) < 0)
{
perror("listen failed");
closesocket(listeningSocket);
WSACleanup();
exit(EXIT_FAILURE);
}
//Accept
int new_socket;
sockaddr_in client_addr;
int nSizeAddr = sizeof(sockaddr);
if (new_socket = accept(listeningSocket, (struct sockaddr *)&client_addr, &nSizeAddr) < 0)
{
perror("accept failed");
closesocket(listeningSocket);
WSACleanup();
exit(EXIT_FAILURE);
}
while (1)
{
//recv
char buff[100];
if (recv(new_socket, buff, 100, 0) < 0)
{
perror("recv failed");
closesocket(listeningSocket);
WSACleanup();
exit(EXIT_FAILURE);
}
cout << buff << endl;
//send
string sndStr = "Da nhan";
if (send(new_socket, sndStr.c_str(), sndStr.size(), 0) < 0)
{
perror("send failed");
closesocket(listeningSocket);
WSACleanup();
exit(EXIT_FAILURE);
}
}
//close socket
closesocket(new_socket);
//Cleanup winsock
WSACleanup();
return 0;
}
Client:
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <iostream>
#include <string>
#define MY_PORT 8888
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//Init winsock
WSADATA SData;
if (WSAStartup(0x0202, &SData) != 0)
{
cout << "KHONG THE KHOI DONG WINSOCK";
return 1;
}
//Init socket
int clientSocket;
if (clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) < 0)
{
perror("socket failed");
WSACleanup();
exit(EXIT_FAILURE);
}
//Set IP and PORT
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(MY_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY; //Vi Client-Server chung 1 may
//Connect
if (connect(clientSocket, (SOCKADDR*)&server_addr, sizeof(server_addr)) < 0)
{
perror("connect failed");
closesocket(clientSocket);
WSACleanup();
exit(EXIT_FAILURE);
}
while (1)
{
//Send
string sndStr;
getline(cin, sndStr);
if (send(clientSocket, sndStr.c_str(), sndStr.size(), 0) < 0)
{
perror("send failed");
closesocket(clientSocket);
WSACleanup();
exit(EXIT_FAILURE);
}
//Recv
char buff[100];
if (recv(clientSocket, buff, 100, 0) < 0)
{
perror("recv failed");
closesocket(clientSocket);
WSACleanup();
exit(EXIT_FAILURE);
}
cout << buff << endl;
}
//Close socket
closesocket(clientSocket);
//Cleanup Winsock
WSACleanup();
}
It had an error at the accept step but I don't know what was the error name. How can I fix it?
The client_socket value turn out INVALID_SOCKET.
EDIT: New problem found - I still don't believe that using INADDR_ANY as a client address is good, but that isn't actually the problem here.
Instead the problem is in the line:
if (clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) < 0)
Note that < has higher precedence than =, so you assign a boolean value to clientSocket here. The similar line in the server code has parenthesis added that makes it work correctly.
Working line in the server code:
if ((listeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
OLD ANSWER: I still stand by this, but it isn't the problem here
.
This is your problem right here (in the client):
server_addr.sin_addr.s_addr = INADDR_ANY; //Vi Client-Server chung 1 may
The way sockets work, is that you create a server socket that listens for incoming connections, and on creation you tell it who to accept connections from. Either from a specific address, a range of addresses, or just from anybody. The third option is the most common one here, and the one you have chosen in your server (bind to address INADDR_ANY).
This part is good.
However, when the client has to connect to the server, you cannot just say: "Connect to whatever!" and expect it to find your server (or anything at all). So when you try to connect with the client socket you have to give it the actual address of the server.
I found a example of how to do this:
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr*) & serv_addr, sizeof(serv_addr)) < 0)
Change the address to the correct one for your server, if localhost (127.0.0.1) don't work for you.

Simple UDP socket code, sending and receiving messages

I am just learning UDP sockets and this is my first code involving it. I have two programs which send and receive messages back and forth. My question is it seems I have to declare which IP address I am sending/receiving from multiple times throughout the code as it changes but I feel there is a better way to do this without changing the inet_addr manually within the codes. From my reading it looks like sendto and recvfrom may be able to help but I am unsure how to use them in this context. If anyone could show me how to fix my simple problem I would greatly appreciate it! Thanks
CODE 1: Send then Receive
int main(int argc, char *argv[])
{
//initialize socket and structure
int socket_info;
struct sockaddr_in server;
char message[100];
char incoming_message[100];
printf("Input Message: ");
fgets(message, 100, stdin);
//create socket
socket_info = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_info == -1) {
printf("Could not create socket");
}
//assign local values
server.sin_addr.s_addr = inet_addr("172.21.8.178");
server.sin_family = AF_INET;
server.sin_port = htons( 1100 );
//binds connection
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Bind");
//assign new value to connect to
server.sin_addr.s_addr = inet_addr("172.21.8.179");
//checks connection
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Connected");
//sends message
if(send(socket_info, message, strlen(message), 0) <0) {
perror("Send failed");
return 1;
}
puts("Message Sent");
//receives message back
if(recv(socket_info, incoming_message, sizeof(incoming_message), 0) <0) {
puts("Received failed");
return 1;
}
puts("Message received");
puts(incoming_message);
close(socket_info);
}
CODE 2: Receive then Send
int main(int argc, char *argv[])
{
//initialize socket and structure
int socket_info;
struct sockaddr_in server;
char incoming_message[100];
//create socket
socket_info = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_info == -1) {
printf("Could not create socket");
}
//assign values
server.sin_addr.s_addr = inet_addr("172.21.8.179");
server.sin_family = AF_INET;
server.sin_port = htons( 1100 );
//checks connection
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Bind");
//Receive an incoming message
if( recv(socket_info, incoming_message, sizeof(incoming_message), 0) < 0) {
puts("Received failed");
return 1;
}
puts("Message received");
puts(incoming_message);
server.sin_addr.s_addr = inet_addr("172.21.8.178");
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Connected");
//Sends message back
char message[100];
printf("Input Message: ");
fgets(message, 100, stdin);
if(send(socket_info, message, strlen(message), 0) <0) {
perror("Send failed");
return 1;
}
puts("Message Sent");
close(socket_info);
}
If you use the function recvfrom()
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
What this function does is it fills a structure of sockaddr with the IP and port information of the packet that it has just received. For example, if your code that sends first then receives sends a packet to the receiver, the receiver should be able to fill the structure values of sin_addr and sin_port with the correct values. You can then make a call of sendto() with this information in order to send it to the correct machine.
Here's the man pages for these functions:
https://linux.die.net/man/2/recvfrom
https://linux.die.net/man/2/sendto
Try using this:
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)
127.0.0.1 is the loopback IP. The address is used to establish an IP connection to the same machine, which seems to be your case.
A detailed way to solve the problem can be found here

How to use 2 sockets PF_INET and PF_PACKET at the same time?

I have the following 2 functions
int listen_socket(unsigned int ip, int port, char *inf)
{
struct ifreq interface;
int fd;
struct sockaddr_in addr;
int n = 1;
DEBUG(LOG_INFO, "Opening listen socket on 0x%08x:%d %s\n", ip, port, inf);
if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
DEBUG(LOG_ERR, "socket call failed: %s", strerror(errno));
return -1;
}
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = ip;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) {
close(fd);
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &n, sizeof(n)) == -1) {
close(fd);
return -1;
}
strncpy(interface.ifr_ifrn.ifrn_name, inf, IFNAMSIZ);
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,(char *)&interface, sizeof(interface)) < 0) {
close(fd);
return -1;
}
if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
close(fd);
return -1;
}
return fd;
}
int raw_socket(int ifindex)
{
int fd;
struct sockaddr_ll sock;
DEBUG(LOG_INFO, "Opening raw socket on ifindex %d\n", ifindex);
if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
DEBUG(LOG_ERR, "socket call failed: %s", strerror(errno));
return -1;
}
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
sock.sll_family = AF_PACKET;
sock.sll_protocol = htons(ETH_P_IP);
sock.sll_ifindex = ifindex;
if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
DEBUG(LOG_ERR, "bind call failed: %s", strerror(errno));
close(fd);
return -1;
}
return fd;
}
Both are socket listener functions.
I used these functions in my application in this way
fd = listen_socket(INADDR_ANY, 67, client_config.interface);
fd2 = raw_socket(client_config.ifindex);
Now if I send packet to my application (with destination = ip of the interface and port=67). What socket should catch my packet? is it fd2 or fd or both?
And if I send a packet to my application (with destination = broacast:255.255.255.0 and port=67). What socket should catch my packet? is it fd2 or fd or both?
Both sockets will receive that packet. As each packet arrives from the network driver to the kernel, it is duplicated and sent to all PF_PACKET (layer 2) sockets. The packet is also sent to the layer 3 (IP/TCP) kernel code and from there, to the addressed socket.
If this didn't happen, running a separate program doing raw packet captures (e. g. wireshark) would prevent any other communications over the network.

Generation of unique IP-port using bind(0)

I need to generate port numbers for some programm. Google tells, that bind with zero-port generates binds unused port. I want to bind zero-port, remember it's number, close port. Trying to do this? but netstat doesn't see my programm's port. Linux 2.6.27
int sfd;
struct sockaddr_in my_addr;
sfd = socket(PF_INET , SOCK_STREAM, 0);
if (sfd == -1)
{
printf("socket error\n");
return -1;
}
memset(&my_addr, 0, sizeof(struct sockaddr_in ));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = INADDR_ANY;
my_addr.sin_port = 0;
if (bind(sfd, (struct sockaddr_in *) &my_addr,
sizeof(struct sockaddr_in)) == -1)
printf("bind error\n");
if (listen(sfd, LISTEN_BACKLOG) == -1)
printf("listen error\n");
bind() expects a sockaddr* not a sockaddr_in*:
bind(sfd, (struct sockaddr *) &my_addr, sizeof(my_addr))
Other than that, I don't see any other errors. Binding to port 0 is the correct way to bind to a random available port. If bind() and listen() do not report a failure then netstat should see an open port. Use getsockname() to find out which port bind() actually chose, eg:
int sfd = socket(PF_INET , SOCK_STREAM, 0);
if (sfd == -1)
{
printf("socket error: %d\n", errno);
return -1;
}
struct sockaddr_in my_addr;
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = INADDR_ANY;
my_addr.sin_port = 0;
if (bind(sfd, (struct sockaddr *) &my_addr, sizeof(my_addr)) == -1)
{
printf("bind error: %d\n", errno);
close(sfd);
return -1;
}
if (listen(sfd, LISTEN_BACKLOG) == -1)
{
printf("listen error: %d\n", errno);
close(sfd);
return -1;
}
memset(&my_addr, 0, sizeof(my_addr));
socklen_t my_addrlen = sizeof(my_addr);
if (getsockname(sfd, (struct sockaddr *) &my_addr, &my_addrlen ) == -1)
{
printf("getsockname error: %d\n", errno);
close(sfd);
return -1;
}
printf("listening on port: %hu\n", ntohs(my_addr.sin_port));

c++ UDP relay application latency

I want to receive UDP packets from a server application (on the same computer) and forward it to an UDP receive app on a different port.
The server app is not mine, nor do i have the source code.
The UDP receive app is a Java application.
If i bind the Java application directly to the server app port, there is very low latency, but if i connect it to the relay appĀ“port i get almost one second of delay.
The receiving port has to be non-blocking.
#define rcv_length 160
fd_set fds;
int n;
struct timeval tv;
void CMClient::startUDPListener(){
CMport_number = 32200;
remoteAddrLen = sizeof(struct sockaddr_in);
if (WSAStartup(0x0101, &CMw) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
CMsd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (CMsd == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
exit(0);
}
CMserver.sin_family = AF_INET;
CMserver.sin_port = htons(CMport_number);
CMserver.sin_addr.s_addr = inet_addr("127.0.0.1");
long rc=bind(CMsd,(SOCKADDR*)&CMserver,sizeof(SOCKADDR_IN));
if(rc==SOCKET_ERROR)
{
printf("Error: bind code: %d\n",WSAGetLastError());
}
}
void CMClient::updateData(UDPServer* svr, int CMnr){
FD_ZERO(&fds);
FD_SET(CMsd, &fds);
tv.tv_sec = 0;
tv.tv_usec = 1;
n = select ( CMsd, &fds, NULL, NULL, &tv ) ;
if (FD_ISSET(CMsd, &fds))
{
FD_CLR(CMsd,&fds);
char* rcvBuffer = new char[rcv_length];
long rc=recv(CMsd,rcvBuffer,rcv_length,0); //receive
if(rc!=SOCKET_ERROR)
{
rcvBuffer[0] = CMnr;
sendto(svr->sd, (char*)rcvBuffer, rcv_length, 0, (struct sockaddr*)&svr->server, sizeof(svr->server)) != (int)sizeof(rcvBuffer); //send
}
if(rcvBuffer)
delete [] rcvBuffer;
}
}
The UDP server to send to the Java application is initialized as follows:
void UDPServer::startUDPServer(){
if (WSAStartup(0x0101, &w) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
exit(0);
}
server.sin_family = AF_INET;
server.sin_port = htons(port_number);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(sd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1)
{
fprintf(stderr, "Could not connect name to socket.\n");
stopUDPServer();
}
}
The main calls
UDPServer* udpsvr;
udpsvr = new UDPServer;
udpsvr->startUDPServer();
while(1){
CM->updateData(udpsvr, CMid);
}
Any help would be appreciated why i get that much delay.
The data received from the Java app is correct but ~1 second delay.
Thank you,
Regards
Don't use bind() on client. Use connect().
Summing up, for UDP:
Server:
socket()
bind()
Client:
socket()
connect()
Example of code for server:
// socket()
fd_ = socket(AF_INET, SOCK_DGRAM, 0);
if (fd_ < 0) {
throw std::runtime_error ("Client socket error");
}
// connect()
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
struct in_addr addr;
inet_aton(address.c_str(), &addr);
bcopy(&addr, &serv_addr.sin_addr.s_addr, sizeof(addr));
if (connect(fd_, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
::close(fd_);
throw std::runtime_error ("Client socket error");
}
Example of code for client:
// socket()
fd_ = socket(AF_INET, SOCK_DGRAM, 0);
if (fd_ < 0) {
throw std::runtime_error ("Client socket error");
}
// connect()
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
struct in_addr addr;
inet_aton(address.c_str(), &addr);
bcopy(&addr, &serv_addr.sin_addr.s_addr, sizeof(addr));
if (connect(fd_, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
::close(fd_);
throw std::runtime_error ("Client socket error");
}
Finally, you may want to have a look at flushing UDP buffers.