Winsock problems sending data C++ - c++

I'm trying to code a simple FTP client with Winsock.
I have the following code:
using namespace std;
#include <iostream>
#include <cstring>
#include <cstdio>
#include <winsock.h>
#include <windows.h>
int main() {
const int MAX_TRIES = 10;
char * host = "localhost";
int port = 21;
char * userName = "b8_8780454";
char * pass = "test";
char * testFileSource = "C:\\Windows\\notepad.exe";
WSADATA WSAData;
SOCKADDR_IN server;
SOCKET sock;
WSAStartup(MAKEWORD(2,2), &WSAData);
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
cout<<"fail";
return -1;
}
server.sin_family = PF_INET;
server.sin_port = htons(port);
server.sin_addr = *((struct in_addr *)gethostbyname(host)->h_addr);
memset(server.sin_zero,0,8);
int errorCode = connect(sock, (LPSOCKADDR)&server, sizeof(struct sockaddr));
int tries = 0;
while (errorCode == SOCKET_ERROR) {
if (tries >= MAX_TRIES) {
cout<<"fail 2";
return -1;
}
errorCode = connect(sock, (LPSOCKADDR)&server, sizeof(struct sockaddr));
tries++;
}
char serverMsg[2048];
Sleep(1000);
cout<<"Waiting for server response..."<<endl;
int r = recv(sock,serverMsg,2048,0);
serverMsg[r] = '\0';
cout<<endl<<endl<<"Server said: "<<endl<<serverMsg<<endl<<endl;
char userB[1024] = "USER ";
strcat(userB,userName);
cout<<"Sending... "<<userB<<endl;
cout<<"sended: "<<send(sock, userB, strlen(userB), 0)<<" bytes"<<endl;
Sleep(1000);
cout<<"Waiting for server response..."<<endl;
serverMsg[0] = '\0';
recv(sock,serverMsg,2048,0); // <-- program keeps lock here
cout<<endl<<endl<<"Server said: "<<endl<<serverMsg<<endl<<endl;
getchar();
return 0;
}
I think the send is not working properly, nevertheless it is returning >0 but on the server side i can't see this client sending any data. I think i maybe a problem with the conection setup, but i have been checking some sites and I am not able to catch the error
This is what the program prints:
Waiting for server response...
Server said:
220-FileZilla Server version 0.9.31 beta
220-written by Tim Kosse (Tim.Kosse#gmx.de)
220 Please visit http://sourceforge.net/projects/filezilla/
Sending... USER b8_8780454
sended: 15 bytes
Waiting for server response...
Server said:
421 Login time exceeded. Closing control connection.
by Tim Kosse (Tim.Kosse#gmx.de)
220 Please visit http://sourceforge.net/projects/filezilla/
In my FTP server I can't see this client sending any data to the server. Any clue?

You need a new line (\n) after your username.
strcat(userB,userName);
strcat(userB,"\n");

Related

How to send data between two remote machines using socket programming?

I'm trying to send data from one remote computer (Ubuntu) to my home computer (High Sierra). I've read a couple of questions here at SO, but they don't seem to give a solution to my problem. I'm connected to the remote computer with ssh, and created and successfully compiled the following programs on both computers.
client.cpp
#include <iostream>
#include <string>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char* argv[])
{
std::string address = argv[1];
int port = 38473;
int success;
// http://man7.org/linux/man-pages/man2/socket.2.html
int server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1)
return errno;
sockaddr_in socket_address{};
socket_address.sin_family = AF_INET;
socket_address.sin_port = htons(port); // htons - Host to Network Short. Flip endianness to match machine.
success = inet_pton(AF_INET, address.c_str(), &socket_address.sin_addr); // Pointer (to String) to Number.
if (success <= 0)
return errno;
success = connect(server_socket, (sockaddr*)&socket_address, sizeof(socket_address));
if (success == -1)
return errno;
std::cout << "Connected" << std::endl;
for (int i = 0; i < 10; ++i)
write(server_socket, "Hello!\n", 7);
}
server.cpp
#include <iostream>
#include <string>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char* argv[])
{
std::string address = "127.0.0.1";
int port = 38473;
int success;
// http://man7.org/linux/man-pages/man2/socket.2.html
int listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == -1)
return errno;
sockaddr_in socket_address{};
socket_address.sin_family = AF_INET;
socket_address.sin_port = htons(port); // htons - Host to Network Short. Flip endianness to match machine.
success = inet_pton(AF_INET, address.c_str(), &socket_address.sin_addr); // Pointer (to String) to Number.
if (success <= 0)
return errno;
// http://man7.org/linux/man-pages/man2/bind.2.html
success = bind(listen_socket, (sockaddr*)&socket_address, sizeof(socket_address));
if (success == -1)
return errno;
// http://man7.org/linux/man-pages/man2/listen.2.html
success = listen(listen_socket, 10);
if (success == -1)
return errno;
sockaddr_in client_address;
socklen_t client_address_size = sizeof(client_address);
int client_socket = accept(listen_socket, (sockaddr*)&client_address, &client_address_size);
if (client_socket == -1)
return errno;
close(listen_socket);
size_t buffer_size = 4096;
char buffer[buffer_size];
ssize_t bytes_received;
std::cout << "Connected" << std::endl;
while (true)
{
memset(buffer, 0, buffer_size);
// http://man7.org/linux/man-pages/man2/recvmsg.2.html
if ((bytes_received = read(client_socket, buffer, buffer_size)) <= 0)
return 0;
std::cout << "Message: " << buffer << std::endl;
}
}
When running both programs on the same machine (where the client executable takes 127.0.0.1 as argument in the command line), it works perfectly and the data is sent. When trying to run my local computer as a server and running client.cpp from the remote, I get the error code 111 (connection refused).
After reading various tutorials/blogs/posts, this seems to be that:
The port currently isn't listening.
The firewall is preventing the connection.
I've tried solving this by doing the following.
The port currently isn't listening.
As the remote machine is trying to connect to my public IP-address, I have to forward a port to my local machine. I logged in to my router and added an entry to forward the port 38473 to my private IP-address. This port was randomly chosen as iana had marked it unassigned, and it was quite large. Since I can send data when running both programs on one machine, I assume the port isn't the issue.
The firewall is preventing the connection.
I've made sure to disable my firewall the local machine (In System Preferences -> Security & Privacy -> Firewall) and made an entry in my router allowing messages from the remote machine (using its public IP-address) via port 38473.
I still don't seem to be able to connect. I ran Wireshark and could see that the remote did send a SYN request, but got a [RST, ACK] in return. The RST flag seems to be a way for the firewall to terminate a connection, but I don't see why it would do that considering my previous configurations above.
What am I doing wrong?
Adjust your server code to listen to the IP of the ethernet card you are interested in on the computer, OR:
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

Client Not Acting Correctly

I've made two C++ files, one for a server and then a client. As you can see below in the code, I wanted to display to the client that they have been connected, and their ID as well, but when I try to connect, it clears the console correctly, but doesn't display their ID. I noticed that when I close the server and the client is still running, the client then displays the ID. Not too sure what the problem is, will be awaiting your replies! Thanks in advance, and here's the code.
Server:
// First, we'll include all the required files
#include <winsock.h>
#include <iostream>
#include <Windows.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib") // Require this lib for winsock
SOCKADDR_IN addr; // This structure saves the address and ports of the server
int addrlen = sizeof(addr); // This saves the length of the address
int Counter; // Counts how many connected clients there are
SOCKET sConnect; // Socket for incoming connections
SOCKET sListen; // Socket for listening
SOCKET *Connections; // Socket for all the connections
// Init the winsock library
int InitWinSock()
{
int Val = 0; // Make a default
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
Val = WSAStartup(DllVersion, &wsaData); // Initialise winsock
return 0;
}
int main()
{
system("color 0a"); // Change the console color to black-green
cout << "Server Started." << endl;
// Winsock Init
int Val = InitWinSock();
if(Val != 0)
{
// If WinSock Init fails, display an error
MessageBoxA(NULL, "Error while starting WinSock!", "Error", MB_OK | MB_ICONERROR);
exit(1); // Stop the procedure
}
Connections = (SOCKET*) calloc(64, sizeof(SOCKET));
// Init the sockets
sListen = socket(AF_INET, SOCK_STREAM, NULL);
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Server address, 127.0.0.1 is localhost
addr.sin_port = htons(2222); // Server port
addr.sin_family = AF_INET; // This is the type of connection
bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); // Bind server to address and port
listen(sListen, 64); // Listen for any incoming connections
while(true)
{
if(sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen))
{
Connections[Counter] = sConnect;
char *Name = new char[64]; // The name of the client
ZeroMemory(Name, 64); // We make the char empty
sprintf(Name, "%i", Counter);
send(Connections[Counter], Name, 64, NULL); // We send the ID to the client
cout << "New Connection!" << endl;
Counter ++; // Increase the amount of clients
} // end if accept the connection
Sleep(50); // Wait 50 milliseconds
} // end while search for connections
}
Client:
#include <iostream>
#include <winsock.h>
#include <Windows.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
SOCKET sConnect; // The connection socket
SOCKADDR_IN addr; // The server adress
int Startup_WinSock()
{
WSADATA wsaData;
WORD DllVersion = MAKEWORD(2, 1);
int Val = WSAStartup(DllVersion, &wsaData);
return Val;
}
int main()
{
system("color 0a");
int Val = Startup_WinSock();
if(Val != 0)
{
cout << "Can't Startup WinSock!" << endl; // Display error
exit(1);
}
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(2222);
addr.sin_family = AF_INET;
cout << "Please press [ENTER]" << endl;
cin.get();
Val = connect(sConnect, (SOCKADDR*)&addr, sizeof(addr)); // Connect with the server
if(Val != 0)
{
cout << "Can't reach the server!" << endl;
main (); // Try again
}
else
{
system("cls"); // Clear the screen
int ID;
char *nID = new char[64]; // Client's ID
char *hello = new char[64]; // Message from the server
ZeroMemory(nID, 64);
ZeroMemory(hello, 64);
recv(sConnect, nID, 64, NULL); // Receive ID from server
recv(sConnect, hello, 64, NULL); // Receive message from the server
ID = atoi(nID); // Cast to an int
cout << hello << endl;
cout << "Your ID: " << ID << endl;
cin.get();
}
return 0;
}
recv(sConnect, nID, 64, NULL); // Receive ID from server
recv(sConnect, hello, 64, NULL); // Receive message from the server
First, you have no error checking here. You need to add error checking throughout the program or it will be impossible to troubleshoot.
Second, you have no message handling here. What happens if the first recv gets 3 bytes? You'll wind up reading the rest of the ID into the hello field.
Third, you don't send any messages. So the second recv will wait until the read attempt fails, which is when the server is terminated.
In the server you only send the id, but nothing more, meaning the client will try to receive something which haven't been sent and will block forever until it receives anything.
Oh, and you have a memory leak in the server, you allocate memory for the name (which you only clear, but doesn't actually set to anything) but you never free the memory anywhere. No need for dynamic allocation here anyway.

Accept() (Winsock 2) stops the program

I have a program that serves both as client and as server without multi-threading (as far as I know accept should let the program continue up until a certain connection is occurs).
The thing is, that my friend has a very similar program (not multithreaded) that also serves as both client AND server and it totally works, I'm trying to accomplish the same thing and accept() stops the program.
The code is as the following:
//main.cpp
#include <iostream>
#include "Client.h"
#include "Server.h"
#pragma comment(lib, "Ws2_32.lib")
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
Server s(6666);
Client c("127.0.0.1", 6666);
cout << "Done";
WSACleanup();
return 0;
}
Server.cpp (two variables, SOCKET _socket and struct sockaddr_in _details):
Server::Server(unsigned short Port) : _socket(0)
{
this->_socket = socket(AF_INET, SOCK_STREAM, 0);
if (_socket < 0)
throw "Invalid socket";
ZeroMemory(&this->_details, sizeof(this->_details));
this->_details.sin_family = AF_INET;
this->_details.sin_port = htons(Port);
this->_details.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
if (bind(this->_socket, (const struct sockaddr*)&this->_details, sizeof(this->_details)) != 0)
{
throw "Bind Unsuccessful";
}
this->AcceptConnections();
}
void Server::AcceptConnections()
{
if (listen(this->_socket, SOMAXCONN) != 0)
throw "Listen Unsuccessful";
void* buf = NULL;
string ans("Accepted");
int client;
struct sockaddr_in client_addr;
int addrlen = sizeof(client_addr);
client = accept(this->_socket, (struct sockaddr*)&client_addr, &addrlen);
/*THIS IS WHERE THE PROGRAM STOPS... AWAITING CONNECTIONS*/
//NEVER REACHING THE CODE HERE
int recvBytes = this->Receive(buf, MY_MAX_LEN);
if (recvBytes <= 0)
{
throw "Client disconnected";
}
this->Send((void*)ans.c_str(), ans.length());
closesocket(client);
closesocket(this->_socket);
}
And client.cpp is irrelevant as it doesn't even encounter its code.
Why does this happen? How come my friend has a code with no multi-threading that has both client and server. By the way, Send and Receive are functions implemented by me.

Winsock UDP filesending error 10040

This is my sending programm.
#pragma once
#pragma comment(lib,"Ws2_32.lib")
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
WSAData wsaData;
WORD DllVersion = MAKEWORD(2,2);
int startup_RetVal = WSAStartup(DllVersion, &wsaData);
SOCKET sSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
SOCKADDR_IN addr;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(22222);
char buf[200000] = "AR*REF=";
int send_RetVal = sendto(sSocket, buf, 200000, NULL, (SOCKADDR*)&addr, sizeof(addr));
if(send_RetVal == SOCKET_ERROR)
{
cout <<" An error occured " << WSAGetLastError() << endl;
getchar();
}
return 0;
}
I get a WSAEMSGSIZE (10040) error.
The goal is to send a 100Kbytes file over udp. I was told that similar error on .NET was solved this way :
IPHostEntry^ IPHostTV;
IPEndPoint^ send_tv_ip;
Socket^ UDPSendTV;
int PortSendTV;
System::String^ IPSend;
send_tv_ip =
gcnew IPEndPoint(IPHostTV->AddressList[0], PortSendTV);
UDPSendTV =
gcnew Socket(send_tv_ip->Address->AddressFamily, SocketType::Dgram, ProtocolType::Udp);
//Increasing buffer and timeout
UDPSendTV->SendTimeout = 1000;
UDPSendTV->SendBufferSize = 100000;
UDPSendTV->SendTo(buff1, 0, size1, SocketFlags::None, send_tv_ip);
How do I modify my sockets so they work correctly?
The message size over UDP is limited by the protocol to ~64KB by the 16-bit message size field in the UDP header. There is no workaround.
(well, except for sending multiple messages per protocol unit).

Address Already in Use.

Recently I have been working on some client-side code for sending and receiving messages from a server using threading. The below code behaves strangely when run. Upon inputting a message to send to the server, the code completes the task, albeit with a "socket already in use" error, the server gets it. But every subsequent message I attempt to send to the server is not received immediately, yet it is seemingly all received at once when the client program terminates.
(Additionally, I am certain the error is client-side, the strange behavior isn't exhibited if one comments the output function.)
How can I fix this error?
Client
#include <stdio.h>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string>
#include <iostream>
#include <errno.h>
#include <pthread.h>
void* input(void* ptr)
{
int on = 1;
bool *input_done = ((struct thread_args*)ptr)->process_done;
struct addrinfo *res = ((struct thread_args*)ptr)->result;
char msg[256];
int sock = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof(on));
bind(sock,res->ai_addr,res->ai_addrlen);
connect(sock,res->ai_addr,res->ai_addrlen);
cin.getline(msg,256);
if (msg[0] == '/') {exit(1);}
send(sock,msg,sizeof msg,0);
cout << "You:" << msg << endl;
*input_done = 1;
close(sock);
pthread_exit(NULL);
}
void* output(void* ptr)
{
int on = 1;
bool *output_done = ((struct thread_args*)ptr)->process_done;
struct addrinfo *res = ((struct thread_args*)ptr)->result;
char msg[256];
int sock = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
bind(sock,res->ai_addr,res->ai_addrlen);
connect(sock,res->ai_addr,res->ai_addrlen);
recv(sock,msg,sizeof msg,0);
cout << "Recieved:" << msg;
*output_done = 1;
close(sock);
pthread_exit(NULL);
}
void io_client()
{
//thread function variables
pthread_t t1,t2;
bool input_done = 1, output_done = 1;
//socket setup variables
struct addrinfo hints, *res;
memset(&hints,0,sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("localhost","8080",&hints,&res);
//setting up structures to pass data to threaded functions
struct thread_args i_args, o_args;
i_args.result = res; i_args.process_done = &input_done;
o_args.result = res; o_args.process_done = &output_done;
while(1)
{
if (output_done)
{
pthread_create(&t2,NULL,output,&o_args);
output_done = 0;
}
if (input_done)
{
pthread_create(&t1,NULL,input,&i_args);
input_done = 0;
}
}
}
int main()
{
io_client();
}
Server
void server()
{
struct addrinfo hints, *res;
int sock=-1, newsock=-1;
int length, on=1;
char **address_list; int entries = 0;
//fd_set read_fd;
//struct timeval timeout;
char buffer[100];
memset(&hints,0,sizeof hints);
res = NULL;
memset(&res,0,sizeof res);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("localhost","8080",&hints,&res);
sock = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof(on));
bind(sock,res->ai_addr,res->ai_addrlen);
listen(sock,10);
while(1)
{
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
socklen_t len;
len = sizeof addr;
newsock = accept(sock,NULL,NULL);
getpeername(newsock,(struct sockaddr*)&addr,&len);
struct sockaddr_in *s = (struct sockaddr_in*)&addr;
inet_ntop(AF_INET,&s->sin_addr,ipstr,sizeof ipstr);
length = 100;
setsockopt(newsock,SOL_SOCKET,SO_RCVLOWAT, (char*)&length,sizeof length);
recv(newsock,buffer,sizeof buffer,0);
cout << buffer << endl;
}
if (newsock != -1)
{
close(newsock);
}
if (sock != -1)
{
close(sock);
}
}
int main()
{
server();
}
It looks like you are trying to have your client bind() to the same port as the server. That's not necessary. And worse, you are trying to bind to to the IP address of the server - which is also a bigger problem. In general, for client sockets that are to call the connect() function, you should just have your socket bind to port 0 and IP 0, thus letting the OS pick a randomly available port for you and enabling use the right local IP address and adapter for the connection. You can call getsockname() to discover what port the OS picked for you after you call connect.
And if you let the OS pick the client port for you, you won't need that SO_REUSESADDR call. Although, your server code could call it for cases where it needs to restart after shutting down with connections still pending to close.
Also. you aren't checking the return value of any of your socket calls. That's probably why you are getting some mysterious results. The call to bind() is more likely failing because you are specifying the server IP, but connect() is succeeding because it will auto-bind the socket if it hasn't already.
Here's a cleaned up version of you input() function. Converting your output() function is an exercise left up to the reader. If you follow my example, you'll be in good shape.
void* input(void* ptr)
{
int on = 1;
bool *input_done = ((struct thread_args*)ptr)->process_done;
int ret;
int success = true;
struct sockaddr_in addrLocal = {};
struct addrinfo *res = ((struct thread_args*)ptr)->result;
char msg[256];
int sock = socket(AF_INET, SOCK_STREAM, 0);
success = (sock != -1);
if (success)
{
addrLocal.sin_family = AF_INET;
addrLocal.sin_port = INADDR_ANY; // INADDR_ANY == 0 --> pick a random port for me
addrLocal.sin_addr.s_addr = INADDR_ANY; // INADDR_ANY == 0 --> use all appropriate network
ret = bind(sock,(sockaddr*)&addrLocal,sizeof(addrLocal));
if (ret == -1) perror("bind: ");
success = (ret != -1);
}
if (success)
{
ret = connect(sock,res->ai_addr,res->ai_addrlen);
if (ret == -1) perror("connect: ");
success = (ret != -1);
}
if (success)
{
cin.getline(msg,256);
if (msg[0] == '/') {exit(1);}
ret = send(sock,msg,sizeof msg,0);
if (ret == -1) perror("send: ");
success = (ret != -1);
}
if (success)
{
cout << "You:" << msg << endl;
*input_done = 1;
}
if (sock != -1)
{
close(sock);
sock = -1;
}
return NULL;
}
I guess that "SO_REUSEADDR" socket option that you are giving is the problem.
Are you calling that function again and again without closing the client socket ? In that case it will not work. The purpose of this socket option is to "reuse the address when the already opened socket for the same address is in TIME_WAIT state else you will get the mentioned error".
If you client is opening a new connection each and every time, then I must say that you will have to structure your code more efficiently and handle the socket closing scenarios as well.