C++ UDP recvfrom WSAGetLastError 10014 - c++

This may be a duplicate question but I have read the other threads and solutions and found nothing missing in the code. Something is there which I am not able to figure out.
Below is the code for a UDP server
#pragma once
#pragma comment( linker, "/defaultlib:ws2_32.lib" )
#include <io.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <process.h>
#include <winsock.h>
#include <iostream>
#include <windows.h>
#include <string>
#include <stdio.h>
using namespace std;
#define REQUEST_PORT 0x7070
#define TIMEOUT_USEC 300000
#define MAX_RETRIES 3
int port=REQUEST_PORT;
//socket data types
SOCKET serverSocket;
SOCKET cs;
SOCKADDR_IN serverSocketAddr;
SOCKADDR_IN clientSocketAddr;
int senderAddrSize = sizeof (clientSocketAddr);
char *buffer;
char localhost[21];
HOSTENT *hp;
int main(void)
{
try
{
initializeSockets();
}
catch(char* str)
{
LPTSTR Error = 0;
if(FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,WSAGetLastError() | GetLastError(),0,(LPTSTR)&Error,0,NULL) == 0)
{
cout<<str<<endl;
}
else
{
cerr<<Error<<endl;
}
LocalFree(Error);
}
return 0;
}
void initializeSockets()
{
try
{
WSADATA wsadata;
if (WSAStartup(0x0202,&wsadata)!=0)
{
throw "Error in starting WSAStartup()";
}
else
{
buffer="WSAStartup was suuccessful\n";
}
gethostname(localhost,20);
cout<<"hostname: "<<localhost<< endl;
if((hp=gethostbyname(localhost)) == NULL)
{
cout << "Cannot get local host info."
<< WSAGetLastError() << endl;
exit(1);
}
if((serverSocket = socket(AF_INET,SOCK_DGRAM,0))==INVALID_SOCKET)
throw "can't initialize socket";
serverSocketAddr.sin_family = AF_INET;
serverSocketAddr.sin_port = htons(port);
serverSocketAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (::bind(serverSocket,(LPSOCKADDR)&serverSocketAddr,sizeof(serverSocketAddr)) == SOCKET_ERROR)
throw "can't bind the socket";
if(recvfrom(serverSocket,buffer,sizeof(buffer),0,(SOCKADDR *)&clientSocketAddr, &senderAddrSize)==SOCKET_ERROR)
throw "Error";
}
catch(char* str)
{
LPTSTR Error = 0;
if(FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,WSAGetLastError() | GetLastError(),0,(LPTSTR)&Error,0,NULL) == 0)
{
cout<<str<<endl;
}
else
{
cerr<<Error<<endl;
}
LocalFree(Error);
}
}
on recvfrom I am getting the WSAError 10014: The system detected an invalid pointer address in attempting to use a pointer argument of a call.
I tried setting the last two parameters to NULL, it works fine then, which means error is in those two pointer variables. But I have properly casted the sockaddr_in to sockaddr and also initialized the length with the sizeof sockaddr. Still getting the error. Don't know what is missing.

The documentation for recvfrom() is very clear on what causes 10014 (WSAEFAULT):
WSAEFAULT
The buffer pointed to by the buf or from parameters are not in the user address space, or the fromlen parameter is too small to accommodate the source address of the peer address.
You are assigning a string literal to the buffer that you pass to recvfrom():
buffer="WSAStartup was suuccessful\n";
A string literal resides in read-only memory that recvfrom() cannot write to.
Also, buffer is declared as char*, so using sizeof(buffer) is wrong.
You need to allocate writable memory for buffer, and get rid of the useless assignment, eg:
char buffer[65535];
Then sizeof(buffer) will be meaningful.

Related

Data gets cut off when send through a tcp socket in c/c++

Long messages get cut off when I send them through a tcp socket. It differs depending on the destination. When sending and receiving locally on my machine, all goes through. When sending and receiving locally on my server, it gets cut off after the 21846th byte consistently. When sending from my machine to the server, it gets cut off at the 1441th byte consistently. The server is in Stockholm and I'm in the UK. The same problem is also present when the client is on Windows and uses Windows' networking code.
Here the client is supposed to send 29 999 zeros and a null terminator, receive them and print them. When I counted them with wc, I got the figures of actual bytes that I received. So the figures represent a two-way transfer but from testing I can say that the problem has the same properties one-way.
The read/write functions are blocking as far as I can tell, so the problem is not that the data has not arrived fully before the functions exit - a problem described in the man page.
How can I fix this?
Go to the bottom to see solution
Here's the code that I used to test this:
server/main.cpp
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include "aes/aes.hpp"
#include "network.hpp"
#include <thread>
using namespace std;
int main()
{
int server_socket = InitServerSocket(26969);
std::cout << "Listening..." << std::endl;
while (true) {
// accept incoming connections - blocking
int client_socket = accept(server_socket, NULL, NULL);
if (client_socket < 0) {
std::cerr << "Unable to accept";
close(server_socket);
return 1;
}
char long_text[30000];
read(client_socket, long_text, 30000);
std::cout << long_text << std::endl;
write(client_socket, long_text, 30000);
close(client_socket);
}
return 0;
}
InitServerSocket():
int InitServerSocket(int port)
{
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket < 0) {
perror("Unable to create socket");
_exit(1);
}
int result = bind(
server_socket,
(struct sockaddr*)&server_address,
sizeof(server_address));
if (result < 0) {
perror("Unable to bind");
_exit(1);
}
if (listen(server_socket, 1000) < 0) {
perror("Unable to listen");
_exit(1);
}
return server_socket;
}
client/main.cpp
#include <arpa/inet.h>
#include <iostream>
#include <netdb.h>
#include <string.h>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "network.hpp"
using namespace std;
int main()
{
int socket = ConnectToHost("70.34.195.74", 26969);
char long_text[30000];
for (int i = 0; i < 30000; i++)
long_text[i] = '0';
long_text[29999] = '\0';
write(socket, long_text, 30000);
read(socket, long_text, 30000);
std::cout << long_text << std::endl;
CloseConnection(socket);
return 0;
}
ConnectToHost():
int ConnectToHost(char* IPAddress, int PortNo)
{
// create a socket
int network_socket; // socket descriptor ~= pointer ~= fd
network_socket = socket(AF_INET, SOCK_STREAM, 0);
// specify a destination address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET; // specify protocol
server_address.sin_port = htons(PortNo); // specify port
// server_address.sin_addr.s_addr = a.s_addr; // specify resolved ip
server_address.sin_addr.s_addr = inet_addr(IPAddress);
// connect
int connection_status = connect(
network_socket,
(struct sockaddr*)&server_address,
sizeof(server_address));
if (connection_status == -1)
std::cout << "Failed to conect to remote host\n";
return network_socket;
}
Solution:
Here are the wrapper functions I wrote to fix the problem:
int Send(int soc, char* buffer, int size)
{
int ret = -1;
int index = 0;
do {
ret = write(soc, buffer + index, size - index);
index += ret;
} while (ret > 0);
if (ret == -1)
return -1;
else
return 1;
};
int Recv(int soc, char* buffer, int size)
{
int ret = -1;
int index = 0;
do {
ret = read(soc, buffer + index, size - index);
index += ret;
} while (ret > 0);
if (ret == -1)
return -1;
else
return 1;
};
write(client_socket, long_text, 30000);
You have no guarantees, whatsoever, that all 30000 bytes get written, even with blocking sockets. You must check the write()'s return value to determine how many bytes were actually written, then implement the required logic to try again, with whatever's left to be written, and proceed in this manner until all 30000 bytes get written to the socket. This is how sockets always work.
read(socket, long_text, 30000);
Same thing here, you must check the returned value. If the socket has only a hundred bytes of unread data waiting you'll get these 100 bytes and read() will return 100. If there's nothing unread from a blocking socket, read() will block. If the socket ends up receiving a packet with 1 byte, read() returns 1, which tells you that only 1 byte was read.
How can I fix this?
You must always check what every read() and write() returns, and proceed accordingly. If you need to read or write more data from the socket, then try again, and do that.
so the problem is not that the data has not arrived fully before
the functions exit - a problem described in the man page.
The man page also describes what the returned value from read() and write() means: a negative value indicates an error, a positive value indicates how many bytes were actually read or written. Only reading and writing to regular files guarantees that the requested number of bytes will be read or written (unless reading reaches the end of the file).

EFAULT when trying to send char

I am trying to send a single 1 byte value using send however when I try to it fails and sets errno to EFAULT. I am unsure why this is as I am setting the buf argument to the address of the char.
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <unistd.h>
#define INVALID_SOCKET ~0
int main()
{
int s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
struct sockaddr_in sin = {0};
char C0 = 3;
if(s == INVALID_SOCKET){exit(1);}
sin.sin_addr.s_addr = inet_addr(/*ip*/);
sin.sin_port = htons(1935);
sin.sin_family = AF_INET;
printf("Destination IP: %s\n", inet_ntoa(sin.sin_addr));
printf("Destination Port: %u\n", ntohs(sin.sin_port));
if(connect(s, (struct sockaddr*)&sin, sizeof(sin)) == -1){printf("Errno: %d\n", errno);exit(2);}
if(send(s, &C0, 1, 0) == -1)
{
switch(errno)
{
case EFAULT:
{
printf("Error: Invalid memory address\nExiting\n");
close(s);
exit(3);
break;
}
default:
{
printf("Error: %d\nExiting\n", errno);
close(s);
exit(3);
break;
}
}
}
return 0;
}
The problem is that you are creating a raw socket. That means you have to create the full IP packet from scratch to send, which you do not do.
What happens right now is undefined behavior as the send call and the underlying network stack goes out of bounds reading data beyond the single byte you provide.

Why i am getting error of adress family not supported by protocol?

I am implementing two way communications using UDP protocol , intitially i send a message HELO from client to server which successfully displays on server side but when i send message from server to client in reply of HELO so it gives me error: Address family not supported by protocol.
Here's my server code:
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
using namespace std;
int main(void)
{
char write[100];
int MAXBUFLEN=100;
char* buf;
char msg[100];
char swp;
int l,x,y;
int conn_sock,n,err;
struct sockaddr_in server_addr,client_addr;
conn_sock=socket(AF_INET,SOCK_DGRAM,0);
if(conn_sock == -1)
{
perror("\n\nError in making socket and error is");
cout<<"Error No:\t\n"<<errno;
exit(0);
}
server_addr.sin_family= AF_INET;
server_addr.sin_port = 1234;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
err=bind(conn_sock,(struct sockaddr *)&server_addr,sizeof(server_addr)); // binding...
if(err == -1)
{
perror("\n\nError in binding and error is:");
cout<<"Error No:\t\n"<<errno;
exit(0);
}
int s=sizeof(client_addr);
n=recvfrom(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&client_addr,(socklen_t*)s); // reciving HELO from client..
cout<<msg<<endl;
cout<<"The messgae hasbeen recieved from client now enter a reply for HELO msg:"<<endl;
cin>> write;
// sending reply to client
int m=sendto(conn_sock,write,strlen(write),0,(sockaddr *)&client_addr,s); // sending reply to client on reply of helo...
if (m== -1){
perror("talker: sendto");
}
// now recieve mail fromm...
recvfrom(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&client_addr,(socklen_t*)s);
// sending rcpto client
sendto(conn_sock,write,strlen(write),0,(sockaddr *)&client_addr,s);
recvfrom(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&client_addr,(socklen_t*)s);
cout<<"Recpt to: Nu.edu.pk"<<endl;
exit(0);
}
And here's my client code:
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#define SERVERPORT "4950" // the port users will be connecting to
#define MAXBUFLEN 100
using namespace std;
int main(int argc, char*argv[])
{
// declarations
char msg3[]="DATA";
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
char buf[MAXBUFLEN];
socklen_t addr_len;
struct sockaddr_storage their_addr;
char* bigarray;
char msg[]="HELO";
char msg2[]="Mail from: Mahnoorfatima#gmail.com";
int i=0;
char * adress;
char * subject;
char * name;
const char *delim="#";
// getting commandline args into arrays.
adress=argv[i+1];
char* host=strtok(adress,delim );
subject=argv[i+2];
name=argv[i+3];
// putting all in one array
bigarray=adress;
bigarray=subject;
bigarray=name;
if(argc>9){
cout << "Just provide three arguments in commandline,please. " << endl;
}
// gets the name of the host:
int a=gethostname(bigarray, 100);
cout<<"The host of the client is:"<<a<<endl;
int conn_sock,n,m,err;
struct sockaddr_in server_addr;
conn_sock=socket(AF_INET,SOCK_DGRAM,0);
if(conn_sock ==-1)
{
perror("\n\nError in making socket and error is");
cout<<"Error No:\t\n"<<errno;
exit(0);
}
server_addr.sin_family= AF_INET;
server_addr.sin_port = 1234;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
int pp=sizeof(server_addr);
n=sendto(conn_sock,msg,strlen(msg),0,(sockaddr *)&server_addr,pp);//sending HELO to server...
n=recvfrom(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&server_addr,(socklen_t*)pp);
cout<<"Mail from: mahnoorfatima22#gmail.com"<<endl;
n=sendto(conn_sock,msg2,strlen(msg2),0,(sockaddr *)&server_addr,pp);
// sending file to server
// reieving from server rcpto command
recvfrom(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&server_addr,(socklen_t*)pp);
// sending data command to the server....
n=sendto(conn_sock,msg3,strlen(msg3),0,(sockaddr *)&server_addr,pp);
//Sending the filename to server...
if ((n = sendto(sockfd,name,strlen(name), 0,p->ai_addr, p->ai_addrlen)) == -1) {
// perror("Error is sending");
exit(1);
}
// Get the size of the file server sy
addr_len = sizeof their_addr;
if ((n = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,(struct sockaddr *)&their_addr, &addr_len)) == -1) {
// perror("Error in recieving file");
exit(1);
}
cout<<"client: recieved file size: %s\nNumbytes:%d\n"<<buf<<numbytes;
exit(0);
}
The problem is most likely that the recvfrom function expects a pointer to the socket address structure size, while you provide the length by value. That means that the compiler with think that the size you set (sizeof(client_addr)) is interpreted as a pointer, and whatever the structure size is, it's not a valid pointer or pointing to something remotely valid.
That means that the recvfrom might not fill in the peer address structure (client_addr) completely, which leads to your sendto failure.
Try e.g. this instead:
n=recvfrom(conn_sock,msg,sizeof(msg),0,
(struct sockaddr *)&client_addr,&s);
// ^
// |
// Note address-of operator here

Segmentation fault sending a struct through TCP socket

I'm writing a simple program about TCP Socket. What I'm going to do is send whatever 1000 data structure from client to server, but it display segmentation fault....
This is my server:
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
using namespace std;
#pragma pack(1)
struct student
{
int id;
string name;
};
main()
{
struct sockaddr_in socketInfo;
socklen_t fromlen;
int socketHandle;
int portNumber = 8080;
bzero(&socketInfo, sizeof(sockaddr_in)); // Clear structure memory
// create socket
if((socketHandle = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
close(socketHandle);
exit(EXIT_FAILURE);
}
// Load system information into socket data structures
socketInfo.sin_family = AF_INET; //IPv4
socketInfo.sin_addr.s_addr = htonl(INADDR_ANY); // Use any address available to the system
socketInfo.sin_port = htons(portNumber); // Set port number
// Bind the socket to a local socket address
if( bind(socketHandle, (struct sockaddr *) &socketInfo, sizeof(socketInfo)) < 0)
{
close(socketHandle);
perror("bind");
exit(EXIT_FAILURE);
}
listen(socketHandle, 1);
int socketConnection;
while(1)
{
cout<<"Waiting to connect ..."<<endl;
if( (socketConnection = accept(socketHandle, NULL, NULL)) < 0)
{
cout<<"Fail!!"<<endl;
exit(EXIT_FAILURE);
}
//close(socketHandle);
int rc = 0; // Actual number of bytes read
struct student buf;
while(1)
{
rc = recv(socketConnection, &buf, sizeof(struct student)+1, 0);
cout<<"Recieve = "<<rc<<endl;
if (rc<=0)
break;
cout<<buf.id<<endl;
cout<<buf.name<<endl;
}
}
}
This is my client:
#include <iostream>
#include <sstream>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
unsigned long inet_addr(const string a);
string int2str( int val ) // interger convert to string
{
ostringstream out;
out<<val;
return out.str();
}
#pragma pack(1)
struct student
{
int id;
string name;
};
main()
{
struct sockaddr_in remoteSocketInfo;
struct hostent *hPtr;
const char *remoteHost="localhost";
int socketHandle;
int portNumber = 8080;
bzero(&remoteSocketInfo, sizeof(sockaddr_in)); // Clear structure memory
if((hPtr = gethostbyname(remoteHost)) == NULL)
{
cerr << "System DNS name resolution not configured properly." << endl;
cerr << "Error number: " << ECONNREFUSED << endl;
exit(EXIT_FAILURE);
}
if((socketHandle = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
close(socketHandle);
exit(EXIT_FAILURE);
}
// Load system information into socket data structures
memcpy((char *)&remoteSocketInfo.sin_addr, hPtr->h_addr, hPtr->h_length);
remoteSocketInfo.sin_family = AF_INET;
remoteSocketInfo.sin_port = htons(portNumber); // Set port number
if(connect(socketHandle, (struct sockaddr *)&remoteSocketInfo, sizeof(sockaddr_in)) < 0)
{
close(socketHandle);
exit(EXIT_FAILURE);
}
struct student buf[1000];
for (int i=0; i<1000; i++)
{
buf[i].id = i+1;
buf[i].name = "student_" + int2str(i) + "00";
send(socketHandle, &buf[i], sizeof(struct student)+1, 0);
}
}
Result:
Waiting to connect ...
Recieve = 13
1
Segmentation fault (core dumped)
The problem here is that one of the fields in struct student is a std::string object. This can't be sent across the wire directly like you're doing.
Instead, either change it to a fixed-size character array something like this...
struct student
{
int id;
char name[100];
}
... and write your name into there. Or you'll have to send it across the wire in a different way.

buffer overrun issues when using scanf_s

I'm writing a simple client-server application which uses async type sockets. However, when I send a message from a client, I'm getting a buffer overrun exception. Client code:
#include "stdafx.h"
#include <conio.h>
#include <winsock.h>
#include <process.h>
#include <stdlib.h>
#include <Windows.h>
#pragma comment(lib, "wsock32.lib")
#define CS_ERROR 1
#define CS_OK 0
char send_buf[1000];
char recv_buf[1000];
void MyFunction(void * Arg)
{
while(1)
{
int Socket=(*(int *)Arg);
send(Socket, send_buf,1000,0);
int n = recv(Socket,recv_buf,1000,0);
recv_buf[n]=0;
printf(" Answer from Server: %s",&recv_buf[0]);
printf("\n");
}
_endthread();
}
int _tmain(int argc, _TCHAR* argv[])
{
WORD version;
WSADATA wsaData;
int result;
version = MAKEWORD(2,2);
WSAStartup(version,(LPWSADATA)&wsaData);
LPHOSTENT hostEntry;
hostEntry = gethostbyname("127.0.0.1");
if(!hostEntry)
{
printf ("%s", " >>> ERROR (hostEntry NULL)\n");
WSACleanup();
return CS_ERROR;
}
SOCKET theSocket = socket(AF_INET, SOCK_STREAM, 0);
if(theSocket == SOCKET_ERROR)
{
printf ("%s", " ERROR (can't create socket)\n");
return CS_ERROR;
}
else
{
printf ("%s", " >>> Creating socket \n");
}
sockaddr_in serverInfo;
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
serverInfo.sin_port = htons(8888);
result=connect(theSocket,(LPSOCKADDR)&serverInfo,
sizeof(serverInfo));
if(result==SOCKET_ERROR)
{
printf ("%s", " ERROR (can't connect to Server)\n");
return CS_ERROR;
}
else
{
printf ("%s", " >>> Connecting to Server\n");
}
printf("Write a message: ");
scanf_s("%s", send_buf, sizeof(send_buf));
_beginthread(MyFunction,0,(void *)&theSocket);
char a[100];
scanf_s("%s", a, sizeof(a));
return CS_OK;
}
I suppose it has something to do with accessing send_buf\recv_buf in illegal way, but I can't figure what. Any tips?
You're not calling scanf_s properly. scanf_s requires two arguments for string input - one with the pointer to the string, and another for the maximum length of the string.
So you should call it like this:
scanf_s("%s", send_buf, sizeof(send_buf));