Is it posslible to mmap tcp client fd? - c++

I'm trying to mmap tcp client using following code:
sockaddr_in addr,peer;
int server = socket(AF_INET, SOCK_STREAM, 0);
int value = 1;
assert(setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) != -1 );
assert(setsockopt(server, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)) != -1 );
addr.sin_port = htons(8080);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
assert(bind(server, (sockaddr*) &addr, sizeof(addr)) != -1 );
assert(listen(server, 5) != -1 );
socklen_t len;
int client = accept(server, (sockaddr *)&peer,&len);
assert(client != -1);
char *ip = inet_ntoa(peer.sin_addr);
int port = htons(peer.sin_port);
printf("Client accepted: %s:%d\n",ip,port );
auto mapped = (char*) mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED , client, 0);
assert(mapped != (char*) -1); //mmap returns -1
char *str = "Hello client\n";
memcpy(mapped, str, strlen(str)); // send message to client
But mmap returns -1 when client connects.
So is there another way how to mmap client fd or is not possible.

Related

Sending UDP package to Lifx and recvfrom

I am trying to send a broadcast UDP package to all my Lifx devices (wifi lamps). The devices should answer with another package to the same port I sent the first package from.
I am so far, that I see my sent broadcast package in wireshark. I also see the reply from the Lifx lamp.
But my program is stuck on recvfrom.
int sockfd;
struct sockaddr_in saddr_send, saddr_recv;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
int one = 1;
if ((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one))) < 0 ) {
perror("set socket option failed");
exit(EXIT_FAILURE);
}
if ((setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) < 0 ) {
perror("set socket option failed");
exit(EXIT_FAILURE);
}
memset(&saddr_send, 0, sizeof(saddr_send));
memset(&saddr_recv, 0, sizeof(saddr_recv));
// Filling dest information
saddr_send.sin_family = AF_INET; // IPv4
saddr_send.sin_addr.s_addr = INADDR_BROADCAST;
saddr_send.sin_port = htons(PORT);
// Filling source information
saddr_recv.sin_family = AF_INET; // IPv4
saddr_recv.sin_addr.s_addr = INADDR_ANY;
saddr_recv.sin_port = htons(PORT);
// Bind the socket with the server address
if (bind(sockfd, (const struct sockaddr *)&saddr_recv, sizeof(saddr_recv)) < 0 ) {
perror("bind failed");
exit(EXIT_FAILURE);
}
char buffer[BUFF_SIZE];
size_t length;
unsigned size = sizeof(saddr_recv);
char recvbuffer[BUFF_SIZE];
length = sendMessage->getEncodedHeader(buffer, BUFF_SIZE);
int e = sendto(sockfd, buffer, length, 0, (struct sockaddr*) &saddr_send, sizeof(saddr_send));
if (e < 0) {
printf("%i\n", errno);
perror("Send error: ");
}
unsigned int r = recvfrom(sockfd, (void*)&recvbuffer, sizeof(recvbuffer), 0, (struct sockaddr*)&saddr_recv, &size);
if (r < sizeof(lifx_protocol_header)) {
printf("package too short");
}
close(sockfd);
I am not sure if I made a conceptional mistake or if I am to slow with calling recvfrom.
Any idea on additional points I could try to solve my problem?

C++ Receiving UDP broadcast packets

I have written a UDP broadcaster program to broadcast packets on the subnet 192.168.1.255, port 19000 - let's say it runs on Machine A 192.168.1.26. This is based on http://beej.us/guide/bgnet/html/single/bgnet.html#broadcast. With error checking removed, it looks like:
struct hostent* he = gethostbyname("192.168.1.255");
int fd = socket(AF_INET, SOCK_DGRAM, 0);
int broadcast = 1;
int errors = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(int));
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr = *((struct in_addr*) he->h_addr);
memset(addr.sin_zero, '\n', sizeof(addr.sin_zero));
const char* message = "Hi there";
int len = strlen(message);
int bytes_sent = sendto(fd, data, len, 0, (struct sockaddr*) &addr, sizeof(addr));
I have written a corresponding receiver application to be distributed on machines on the same network as the broadcaster. This is based on http://beej.us/guide/bgnet/html/single/bgnet.html#datagram. Again, with error checking removed, this program looks like this:
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo* servinfo;
int rv = getaddrinfo(NULL, "19000", &hints, &servinfo);
int fd = -1;
struct addrinfo* p;
for (p = servinfo; p != NULL; p = p->ai_next)
{
fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
int errors = bind(fd, p->ai_addr, p->ai_addrlen);
int broadcast = 1;
errors |= setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(int));
if (errors == 0)
break;
}
freeaddrinfo(servinfo);
struct sockaddr their_addr;
socklen_t addr_len = sizeof(their_addr);
int bufsize = 4096;
char buf[bufsize];
int bytes_received = recvfrom(fd, &buf[0], bufsize, 0, (struct sockaddr*) &their_addr, &addr_len);
When I run the broadcaster, in Wireshark I can see packets delivered to other machines on the subnet with the expected source address 192.168.1.26 and destination address 192.168.1.255. The payload is correct. However, my receiver application does not pick up the packets.
If I change the broadcaster to send only to a single receiver machine, e.g. 192.168.1.58, the receiver application on that machine receives the packets correctly but obviously no other machine does.
I have disabled the firewalls on both machines.
Can anyone suggest what's wrong?

Data not received back by client via socket [Transport endpoint is already connected]

I have two programs Node-A and Node-B, where Node-A is sending some char* data to Node-B and Node-B is sending an ack (char* data) to Node-A. ie, the clientNodeA_thread is sending data to Node-B's serverNodeB_thread. The code is as below:
NodeA
int main()
{
pthread_t clientNodeA, serverNodeA;
usleep(3000000);
pthread_create(&clientNodeA, NULL, clientNodeA_thread, "clientNodeA");
pthread_create(&serverNodeA, NULL, serverNodeA_thread, "serverNodeA");
usleep(100000000);
pthread_join(clientNodeA, NULL);
pthread_join(serverNodeA, NULL);
return 0;
}
void* clientNodeA_thread(void* pString)
{
int connSock, in, i, ret, flags;
struct sockaddr_in servaddr, NodeAaddr;
struct sctp_status status;
char buffer[MAX_BUFFER+1];
/* Sample input*/
strncpy(buffer, "FrmNodeAClt", 12);
buffer[12]='\0';
connSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );
if(connSock == -1)
die("socket()");
#if 0
bzero( (void *)&NodeAaddr, sizeof(NodeAaddr) );
NodeAaddr.sin_family = AF_INET;
NodeAaddr.sin_port = htons(MY_PORT_NUM_NodeA2);
NodeAaddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
#endif
bzero( (void *)&servaddr, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MY_PORT_NUM_NodeB);
servaddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
ret = connect( connSock, (struct sockaddr *)&servaddr, sizeof(servaddr) );
if(ret == -1)
die("connect()");
ret = sctp_sendmsg( connSock, (void *)buffer, (size_t)strlen(buffer),
NULL, 0, 0, 0, 0, 0, 0 );
return 0;
}
void* serverNodeA_thread(void* pString)
{
int listenSock, connSock, ret, in , flags, i;
struct sockaddr_in servaddr;
struct sockaddr_in src_addr;
struct sctp_initmsg initmsg;
int addr_len = 0;
listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );
bzero( (void *)&servaddr, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
servaddr.sin_port = htons(MY_PORT_NUM_ENB2);
ret = bind( listenSock, (struct sockaddr *)&servaddr, sizeof(servaddr) );
/* Specify that a maximum of 5 streams will be available per socket */
memset( &initmsg, 0, sizeof(initmsg) );
initmsg.sinit_num_ostreams = 5;
initmsg.sinit_max_instreams = 5;
initmsg.sinit_max_attempts = 4;
ret = setsockopt( listenSock, IPPROTO_SCTP, SCTP_INITMSG,
&initmsg, sizeof(initmsg) );
listen( listenSock, 5 );
while( 1 ) {
char buffer[MAX_BUFFER + 1];
int len ;
bzero(buffer, MAX_BUFFER + 1);
printf("Awaiting a new connection\n");
connSock = accept( listenSock, (struct sockaddr *)NULL, (int *)NULL );
if(connSock == -1)
die("accept()");
else
printf("New client connected....\n");
addr_len = sizeof (src_addr);
recvfrom(connSock, buffer, sizeof(buffer), 0, &src_addr, &addr_len);
printf("Received data from NodeB : %s\n", (char*)buffer);
}
}
NodeB
int connSock;
/*NodeA context maintenance */
struct NodeAStruct {
char ipAddr[20];
unsigned int portNum;
};
static int NodeAInstCount;
struct NodeAStruct NodeAInst[7];
int main()
{
pthread_t clientNodeA, serverNodeA;
pthread_create(&serverNodeA, NULL, serverNodeB_thread, "serverNodeA");
usleep(10000000);
pthread_join(clientNodeA, NULL);
pthread_join(serverNodeA, NULL);
return 0;
}
void* serverNodeB_thread(void* pString)
{
int listenSock, ret, flags, i;
struct sockaddr_in src_addr;
struct sockaddr_in servaddr;
struct sctp_initmsg initmsg;
struct sctp_event_subscribe events;
struct sctp_sndrcvinfo sndrcvinfo;
char sendBuffer[MAX_BUFFER+1];
unsigned int NodeA_PORT_NUM;
char* NodeA_IP_ADDR;
char from_ip[1024] = "", myip[2014] = "";
int addr_len = 0;
listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );
bzero( (void *)&servaddr, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
//servaddr.sin_addr.s_addr = htonl("127.0.0.1");
servaddr.sin_port = htons(MY_PORT_NUM_NodeB);
ret = bind( listenSock, (struct sockaddr *)&servaddr, sizeof(servaddr) );
/* Specify that a maximum of 5 streams will be available per socket */
memset( &initmsg, 0, sizeof(initmsg) );
initmsg.sinit_num_ostreams = 5;
initmsg.sinit_max_instreams = 5;
initmsg.sinit_max_attempts = 4;
ret = setsockopt( listenSock, IPPROTO_SCTP, SCTP_INITMSG,
&initmsg, sizeof(initmsg) );
listen( listenSock, 5 );
while( 1 ) {
char buffer[MAX_BUFFER + 1];
int len ;
bzero(buffer, MAX_BUFFER + 1);
printf("Awaiting a new connection\n");
connSock = accept( listenSock, (struct sockaddr *)NULL, (int *)NULL );
if(connSock == -1)
die("accept()");
else
{
printf("New client connected....\n");
addr_len = sizeof (src_addr);
recvfrom(connSock, buffer, sizeof(buffer), 0, &src_addr, &addr_len);
printf("Received message: %s from NodeA IP: %s Port: %u \n", (char*)buffer, inet_ntop(AF_INET, &src_addr.sin_addr, from_ip, sizeof(from_ip)), ntohs(src_addr.sin_port));
strcpy(NodeAInst[NodeAInstCount].ipAddr, inet_ntop(AF_INET, &src_addr.sin_addr, from_ip, sizeof(from_ip)));
NodeAInst[NodeAInstCount].portNum = ntohs(src_addr.sin_port);
printf("NodeA instance [%d] added \n", NodeAInstCount);
/* Send data to NodeA*/
strncpy(sendBuffer, "From NodeB", 12);
sendBuffer[12]='\0';
NodeA_PORT_NUM = NodeAInst[NodeAInstCount].portNum;
usleep(10000000);
ret = sctp_sendmsg( connSock, (void *)sendBuffer, (size_t)strlen(sendBuffer),
NULL, 0, 0, 0, 0, 0, 0 );
if(ret>0) {
printf("Data sent to NodeA \n");
}
else {
printf("Sending data to NodeA failed");
}
usleep(6000000);
NodeAInstCount++;
}
}
}
I am able to send data from Node-A client to Node-B server, and the Node-B is also able to send Ack data (as verified in Wireshark), but it is not reaching Node-A receive code.
Any help in this regard would be highly helpful.
The problem is that you bind the client A socket to the local address, but you don't bind the passive server socket.
Don't bind client sockets, there's often no need for that. You do need to bind the server sockets locally though, or the system will just bind it to a random port when you call listen.
Issue resolved! I just moved the NodeA's socket creation and bind part to the main function so that it would be shared by both client and server threads, and the client and server threads would just do the send and receive functionality.
Thanks #Joachim Pileborg

FIXED: C++ server/client program: "Connection refused"

I'm writing a simple program to transfer files from server to client (both on the same computer for now). Using "telnet 127.0.0.1 [port]", I can succesfully get the file from the server, but when I run the client, the server refuses connection. I suspect that the client is trying to connect to the wrong address, but I'm not sure. I also added some GDB test output if it helps.
Server: "./server 0 4100 bigfile 100 0.01"
int main(int argc, char* argv[])
{
int sockfd;
if(!(sockfd = socket(AF_INET, SOCK_STREAM, 0))) {
error("Failed to create socket");
}
struct sockaddr_in serv_addr, cl_addr;
bzero((void*) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(atoi(argv[2]));
if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
error("Failed to bind");
}
listen(sockfd, 10);
int fd = open(argv[3], O_RDONLY);
int bufsize = atoi(argv[4]);
int packet_period = atoi(argv[5]);
size_t cl_addr_len = sizeof(cl_addr);
char *buf = new char[bufsize];
while(true) {
int sd;
cout << "waiting for client..." << endl;
if(!(sd = accept(sockfd, (struct sockaddr *) &cl_addr, (socklen_t*) &cl_addr_len))) {
error("Failed to acccept");
}
cout << "Accepted client connection" << endl;
lseek(fd, 0, SEEK_SET);
while(int n = read(fd, buf, bufsize)) {
cout << "Transferring " << buf << endl;
usleep(100000);
write(sd, buf, n);
}
}
}
Client: "./client 0 127.0.0.1 4100 bigfile stats"
int main(int argc, char *argv[])
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
error("Failed to open socket");
}
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[2]);
serv_addr.sin_port = htons(atoi(argv[3])); // I tried both htons and htonl
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
error("Failed to connect");
}
int n;
char buf[256];
int fd = open(argv[4], O_RDONLY);
while((n = read(sockfd, buf, 256)) > 0) {
printf("Received: %s\n", buf);
write(fd, buf, n);
}
close(fd);
close(sockfd);
return 0;
}
GDB Output:
(gdb) r
Starting program: [...]/client 0 127.0.0.1 4100 bigfile stats
Breakpoint 1, main (argc=6, argv=0x7fffffffde68) at client.cpp:31
31 if (connect(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
(gdb) p serv_addr
$1 = {sin_family = 2, sin_port = 0, sin_addr = {s_addr = 16777343},
sin_zero = "\000\000\000\000\000\000\000"}
{sin_family = 2, sin_port = 0, sin_addr = {s_addr = 16777343}, sin_zero = "\000\000\000\000\000\000\000"}
So sin_port is wrong: it shouldn't be zero. The code that sets it is:
serv_addr.sin_port = htonl(atoi(argv[3]));
The problem is here. It should be
serv_addr.sin_port = htons(atoi(argv[3]));
Not today's problem but
printf("Received: %s\n", buf);
should be
printf("Received: %.*s\n", n, buf);

Setting Socket Timeout?

Using sockets, I am not sure how to set the timeout?
thanks
int sock, connected, bytes_recieved;
char send_data [128] , recv_data[128];
SOCKADDR_IN server_addr,client_addr;
int sin_size;
int j = 0;
::socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(4000);
server_addr.sin_addr.s_addr = INADDR_ANY;
::bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
::listen(sock, 5);
::fflush(stdout);
while(1)
{
sin_size = sizeof(struct sockaddr_in);
connected = ::accept(sock, (struct sockaddr *)&client_addr, &sin_size);
while (1)
{
j++;
::send(connected, send_data, strlen(send_data), 0);
//dealing with lost communication ?
//and reastablishing communication
//set timeout and reset on timeout error
}
}
::closesocket(sock);
You need to use setsockopt to set the SO_SNDTIMEO and/or SO_RCVTIMEO options.
A socket is in blocking mode by default. If you switch it to non-blocking mode using ioctlsocket(FIONBIO), you can use select() to manage timeouts:
SOCKET sock, connected;
int bytes_recieved;
char send_data [128] , recv_data[128];
SOCKADDR_IN server_addr,client_addr;
int sin_size;
int j = 0, ret;
fd_set fd;
timeval tv;
sock = ::socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(4000);
server_addr.sin_addr.s_addr = INADDR_ANY;
::bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
::listen(sock, 1);
::fflush(stdout);
u_long nbio = 1;
::ioctlsocket(sock, FIONBIO, &nbio);
while(1)
{
FD_ZERO(&fd);
FD_SET(sock, &fd);
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, &fd, NULL, NULL, &tv) > 0)
{
sin_size = sizeof(struct sockaddr_in);
connected = ::accept(sock, (struct sockaddr *)&client_addr, &sin_size);
nbio = 1;
::ioctlsocket(connected, FIONBIO, &nbio);
while (1)
{
j++;
if (::send(connected, send_data, strlen(send_data), 0) < 0)
{
//dealing with lost communication ?
//and reastablishing communication
//set timeout and reset on timeout error
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
FD_ZERO(&fd);
FD_SET(connected, &fd);
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, NULL, &fd, NULL, &tv) > 0)
continue;
}
break;
}
}
closesocket(connected);
}
}
you can use:
fd_set fd;
timeval tv;
FD_ZERO(&fd);
FD_SET(sock, &fd);
tv.tv_sec = time_out(second);
tv.tv_usec = 0;
to set timeout for sending,receiving data.