Connecting to IRC Server C++ Windows 10 Visual Studio - c++

So I am fairly new to C++/C and only learned the language about a week ago so I'm a bit lost. I am trying to build an IRC Client to connect to a server and I can't seem to get it to work. I am using Visual Studio as my IDE and have followed the instructions listed on here for Socket connections: https://learn.microsoft.com/en-us/windows/desktop/winsock/complete-client-code
// Testing.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <iostream>
#include <string>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
SOCKET ConnectSocket = INVALID_SOCKET;
void SendData(string s) {
if (send(ConnectSocket, s.c_str(), sizeof(s.c_str()), 0) == SOCKET_ERROR) {
cout << "send failed: " << WSAGetLastError() << endl;
closesocket(ConnectSocket);
WSACleanup();
}
else { cout << s << endl; }
}
int main()
{
WSADATA wsaData;
// Initialize Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsaData)) {
printf("WSAStartup failed");
system("pause");
}
else { cout << "WinSock Started" << endl; }
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
if (getaddrinfo("38.229.70.22", "6665", &hints, &result)) {
cout << "GetAddrInfo FAILED" << endl;
WSACleanup();
system("pause");
}
// Attempt to connect to the first address returned by
// the call to getaddrinfo
ptr = result;
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
cout << "Error at socket(): " << WSAGetLastError() << endl;
freeaddrinfo(result);
WSACleanup();
system("pause");
}
// Connect to server.
if (connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen) == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
// Should really try the next address returned by getaddrinfo
// if the connect call failed
// But for this simple example we just free the resources
// returned by getaddrinfo and print an error message
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
cout << "Unable to connect to server!\n" << endl;
WSACleanup();
system("pause");
}
else { cout << "CONNECTED!!!" << endl; }
string pass = "PASS none\r\n", nick = "NICK TestUserFoo\r\n", user = "USER guest 0 * :TestUserFoo\r\n", join = "JOIN #etc";
SendData(pass);
SendData(nick);
SendData(user);
SendData(join);
char recvbuf[512];
int iResult;
cout << "Data Sent" << endl;
// shutdown the connection for sending since no more data will be sent
// the client can still use the ConnectSocket for receiving data
/*iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}*/
// Receive data until the server closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, sizeof(recvbuf), 0);
if (iResult > 0)
cout << "Bytes received: " << iResult << endl << recvbuf << endl;
else if (iResult == 0)
cout << "Connection closed\n";
else
cout << "recv failed: " << WSAGetLastError() <<endl;
} while (iResult > 0);
system("pause");
}
I decided to connect to an empty channel on freenode and got the ip of chat.freenode.net by doing a ping-ing it. When I connect, here is my output:
WinSock Started
CONNECTED!!!
PASS none
NICK TestUserFoo
USER guest 0 * :TestUserFoo
JOIN #etc
Data Sent
Bytes received: 62
:card.freenode.net NOTICE * :*** Looking up your hostname...
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╚Σv
Bytes received: 103
:card.freenode.net NOTICE * :*** Checking Ident
:card.freenode.net NOTICE * :*** Found your hostname
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╚Σv
It seems my commands sent for PASS NICK and USER aren't being interpreted or properly sent to the IRC server since I'm not getting a response back. What is going on?

Your problem is:
sizeof(s.c_str())
in
if (send(ConnectSocket, s.c_str(), sizeof(s.c_str()), 0) == SOCKET_ERROR) {
The sizeof operator is returning the size of the char* (which may be 4 bytes or 8 bytes depending if it's a 32-bit or 64-bit application).
You want to change it to:
if (send(ConnectSocket, s.c_str(), s.size(), 0) == SOCKET_ERROR) {

Related

Error "Invalid padding length on received packet" when connecting to winsock server using PuTTY

I'm mostly new to new to networking so I thought I'd start with something simple so I was trying to make a simple C++ echo server. I'm using PuTTY for testing. When I connect to the server through PuTTY I get a PuTTY error of
Invalid padding length received packet
When I check the server console it says that the PuTTY client connected but disconnected immediatelly.
Here's my code.
#include <stdlib.h>
#include <WS2tcpip.h> //includes the winsock file as well
#include <string>
#pragma comment (lib,"ws2_32.lib")
#define PORT 17027
int main()
{
//Initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOK = WSAStartup(ver, &wsData);
if (wsOK != 0)
{
std::cout << "Can't initialize wonsock! Quitting" << std::endl;
return 0;
}
//Create a socket
SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket == INVALID_SOCKET)
{
std::cout << "Can't create socket! Quitting" << std::endl;
return 0;
}
//Bind the socket to an ip address and port
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(PORT);
hint.sin_addr.S_un.S_addr = INADDR_ANY;
bind(listenSocket, (sockaddr *)&hint, sizeof(hint));
//Tell Winsock the socket is for listening
listen(listenSocket, SOMAXCONN);
//Wait for connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listenSocket, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET)
{
std::cout << "Cant accept client! Quitting" << std::endl;
return 0;
}
char host[NI_MAXHOST]; // Client's remote name;
char service[NI_MAXHOST]; // Client's (i.e. port) the client is connected on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXHOST, 0) == 0) // try to get name of client
{
std::cout << host << " connected on port " << service << std::endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST); //get address of client
std::cout << host << " connected on port " << ntohs(client.sin_port) << std::endl;
}
//Close listening socket
closesocket(listenSocket);
//While loop: accept and echo message back to client
char buf[4096];
while (true)
{
ZeroMemory(buf, 4096);
//Wait for client to send data
int bytesReceived = recv(clientSocket, buf, 4096, 0);
if (bytesReceived == SOCKET_ERROR)
{
std::cerr << "Error in recv(). Quitting" << std::endl;
break;
}
if (bytesReceived == 0)
{
std::cerr << "Client disconnected" << std::endl;
break;
}
//Echo message back to client
send(clientSocket, buf, bytesReceived + 1, 0);
}
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
return 0;
}
It looks like you are trying to connect with SSH. Your code is not an SSH server.
To connect to a raw socket server with PuTTY, you need to select the "Raw" connection type.

WinSock c++ inet_ntop always displays 204.204.204.204 (and accept() didn't failed)

I'm trying to make a winsock server and I want to display the client's ip on the server when he connects but that's where there is a problem. Every time I try to connect it display 204.204.204.204. I tried to connect with another computer but the result was the same.
result in localhost
After this, I started looking for people having the same problem as me on this website and I found several people who had the same as me but they all had either the accept or the inet_ntop function that wasn't working correctly. So I check and none of this two functions return an error. Maybe I'm stupid but I really can't figured out what's the problem. (btw english is not my first language so please tell me if you noticed or if my english isn't too bad)
the part of the code that isn't working
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
if (client == INVALID_SOCKET)
{
std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
WSACleanup();
}
else
{
char clientIp[17];
if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
{
std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
}
std::cout << "ip connected: " << clientIp << std::endl;
the whole code if you need it
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string>
#pragma comment(lib, "ws2_32.lib")
int main()
{
std::cout << "--- Tcp/ip Server ---" << std::endl;
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
SOCKET server = socket(AF_INET, SOCK_STREAM, 0);
if (server == INVALID_SOCKET)
{
std::cout << "error in SOCKET(): "<< WSAGetLastError() << std::endl;
WSACleanup();
}
sockaddr_in s;
s.sin_family = AF_INET;
s.sin_addr.s_addr = INADDR_ANY;
s.sin_port = htons(52000);
// bind
if (bind(server, (sockaddr*)&s, sizeof(s)) == SOCKET_ERROR)
{
std::cout << "Error: bind()" << std::endl;
}
//listen
if (listen(server, SOMAXCONN) == SOCKET_ERROR)
{
std::cout << "Error in listen(): " << WSAGetLastError() << std::endl;
WSACleanup();
}
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
if (client == INVALID_SOCKET)
{
std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
WSACleanup();
}
else
{
char clientIp[17];
if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
{
std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
}
std::cout << "ip connected: " << clientIp << std::endl;
// the code isn't finished yet
system("pause");
WSACleanup();
}
return 0;
}
You are passing the address of the wrong variable in the second parameter of accept().
You are passing the address of your SOCKET client variable that you are about to assign the result of accept() to. C++ allows a variable's address to be taken when declaring and initializing the variable in the same statement. But that is not what you want in this case. You need to pass the address of your sockaddr_in from variable instead:
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&from, &clientlen); // <-- &from instead of &client
You are leaving your from variable uninitialized, and your compiler fills uninitialized variables with 0xCC (decimal 204) bytes in debug mode, so that is why you end up seeing 204.204.204.204 (hex 0xCC 0xCC 0xCC 0xCC) from inet_ntop() when you don't initialize your from variable properly.

Socket c++ application in Visual Studio does not work over ethernet connection between two computers

I'm currently working on a simple server/client application using C++ in Visual Studio to send a message from one computer to another via an Ethernet/LAN cable connection. I am using code for both client and server that I found online.
When I run the programs on the same computer, I can receive messages from the server. However, if I run the client program on one computer and run the server program on another computer, I do not receive any messages.
Since I am just using an Ethernet cable to communicate between two computers, I set the IP addresses (from Local Network Sharing, Adapter settings, TCP/IPv4) to be specific for both computers, such that the server computer is 10.0.1.2 and the client computer is 10.0.1.1, both with a subnet mask of 255.255.255.0. And then, in the code, I use addr.sin_addr.s_addr = inet_addr("10.0.1.2") for server and addr.sin_addr.s_addr = inet_addr("10.0.1.1") for client accordingly.
But I am still having the problem of sending messages from one computer to another.
Here is the code:
/////////////////////Client Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <iostream>
int main()
{
//Winsock Startup
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
SOCKADDR_IN addr; //Address to be binded to our Connection socket
int sizeofaddr = sizeof(addr); //Need sizeofaddr for the connect function
addr.sin_addr.s_addr = inet_addr("10.0.1.1");
addr.sin_port = htons(139); //Port = 139
addr.sin_family = AF_INET; //IPv4 Socket
SOCKET Connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Set Connection socket
if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) //If we are unable to connect...
{
MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
return 0; //Failed to Connect
}
std::cout << "Connected!" << std::endl;
int rec = 0;
char MOTD[256];
while (1)
{
recv(Connection, MOTD, sizeof(MOTD), NULL); //Receive Message of the Day buffer into MOTD array
std::cout << "MOTD:" << MOTD << std::endl;
std::cout << "rec:" << rec << std::endl;
rec++;
Sleep(500);
}
}
/////////////////////Server Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <iostream>
int main()
{
//WinSock Startup
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);
return 0;
}
SOCKADDR_IN addr; //Address that we will bind our listening socket to
int addrlen = sizeof(addr); //length of the address (required for accept call)
addr.sin_addr.s_addr = inet_addr("10.0.1.2");
addr.sin_port = htons(139); //Port
addr.sin_family = AF_INET; //IPv4 Socket
SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); //Bind the address to the socket
listen(sListen, SOMAXCONN); //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max Connections
int counter = 0;
SOCKET newConnection; //Socket to hold the client's connection
newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
if (newConnection == 0) //If accepting the client connection failed
{
std::cout << "Failed to accept the client's connection." << std::endl;
}
else //If client connection properly accepted
{
std::cout << "Client Connected!" << std::endl;
while (counter <100)
{
char MD[256] = "Hi there."; //Create buffer with message
send(newConnection, MD, sizeof(MD), NULL); //Send MD buffer
counter++;
}
}
system("pause");
return 0;
}
I really don't know what to do now. I can ping from one computer to another, but I can not make it work to send a message from one computer to another via the Ethernet connection.
The main problem is that the client is connecting to the wrong IP. The server's IP is 10.0.1.2, but the client is trying to connect to 10.0.1.1 instead. That is why it doesn't work across multiple computers. The client needs to connect to the server's IP, not the client's IP.
Also, you are making several other mistakes in general.
On the server side, you are ignoring the return values of bind() and listen(), and accept() returns INVALID_SOCKET (-1) on error instead of 0.
On the client side, you are ignoring the return value of recv(). It returns -1 on error, 0 on graceful disconnect, and > 0 for the number of bytes actually read. You need to pay attention to that, especially when you are sending the read data to std::cout. You are passing a char[] to operator<<, so the data must be null-terminated, but recv() does not do guarantee that. So, either:
add a null terminator to the end of the char[] data after reading it:
int numRead = recv(Connection, MOTD, sizeof(MOTD)-1, NULL);
if (numRead <= 0) break;
MOTD[numRead] = 0; // <-- here
std::cout << "MOTD:" << MOTD << std::endl;
pass the char[] to std::cin.write() instead of operator<<, specifying the actual number of bytes read in the count parameter:
int numRead = recv(Connection, MOTD, sizeof(MOTD), NULL);
if (numRead <= 0) break;
std::cout << "MOTD:";
std::cout.write(MOTD, numRead); // <-- here
std::cout << std::endl;
And your MOTD protocol is not very well designed in general. The server is sending 256 bytes (if you are lucky, send() can send fewer bytes!) for every message, even though only 9 bytes are actually being used. So you are wasting bandwidth. The client is expecting to receive exactly 256 bytes every time (which is not guaranteed, as recv() may receive fewer bytes!). A better design is to have the server send strings that have a terminating delimiter at the end, such as a line break or a null terminator, and then have the client read in a loop until it receives that delimiter, THEN process the data that has been received.
Try something more like this:
/////////////////////Client Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
//Winsock Startup
WSAData wsaData;
int iResult = WSAStartup(MAKEWORD(2, 1), &wsaData);
if (iResult != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
std::cout << "Winsock Startup Failed, Error " << iResult << std:endl;
return 1;
}
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET; //IPv4 Socket
addr.sin_addr.s_addr = inet_addr("10.0.1.2"); //Address to be connected to
addr.sin_port = htons(139); //Port = 139
SOCKET Connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket to establish new connection with
if (Connection == INVALID_SOCKET)
{
iResult = WSAGetLastError();
std::cout << "Failed to Create Socket, Error " << iResult << std::endl;
WSACleanup();
return 1; //Failed to Connect
}
if (connect(Connection, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //If we are unable to connect...
{
iResult = WSAGetLastError();
std::cout << "Failed to Connect, Error " << iResult << std::endl;
closesocket(Connection);
WSACleanup();
return 1; //Failed to Connect
}
std::cout << "Connected!" << std::endl;
int rec = 0;
char buf[256], *ptr, *start, *end;
int numRead;
std::string MOTD;
int iExitCode = 0;
while (true)
{
numRead = recv(Connection, buf, sizeof(buf), NULL); //Receive data
if (numRead == SOCKET_ERROR)
{
iResult = WSAGetLastError();
std::cout << "Failed to Read, Error " << iResult << std:endl;
iExitCode = 1;
break;
}
if (numRead == 0)
{
std::cout << "Server disconnected!" << std::endl;
break;
}
start = buf;
end = buf + numRead;
do
{
// look for MOTD terminator
ptr = std::find(start, end, '\0');
if (ptr == end)
{
// not found, need to read more...
MOTD.append(start, end-start);
break;
}
// terminator found, display current MOTD and reset for next MOTD...
MOTD.append(start, ptr-start);
std::cout << "MOTD:" << MOTD << std::endl;
std::cout << "rec:" << rec << std::endl;
rec++;
MOTD = "";
start = ptr + 1;
}
while (start < end);
}
closesocket(Connection);
WSACleanup();
return iExitCode;
}
/////////////////////Server Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
bool sendAll(SOCKET s, const void *buf, int size)
{
const char *ptr = (const char*) buf;
while (size > 0)
{
int numSent = send(s, ptr, size, NULL);
if (numSent == SOCKET_ERROR) return false;
ptr += numSent;
size -= numSent;
}
return true;
}
int main()
{
//WinSock Startup
WSAData wsaData;
int iResult = WSAStartup(MAKEWORD(2, 1), &wsaData);
if (iResult != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
std::cout << "WinSock Startup Failed, Error " << iResult << std::endl;
return 1;
}
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET; //IPv4 Socket
addr.sin_addr.s_addr = INADDR_ANY; //Address that we will bind our listening socket to. INADDR_ANY = all local IPv4 addresses
addr.sin_port = htons(139); //Port
SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket to listen for new connections
if (sListen == INVALID_SOCKET)
{
iResult = WSAGetLastError();
std::cout << "Failed to Create Socket, Error " << iResult << std::endl;
closesocket(sListen);
WSACleanup();
return 1;
}
if (bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //Bind the address to the socket
{
iResult = WSAGetLastError();
std::cout << "Failed to Bind Socket, Error " << iResult << std::endl;
closesocket(sListen);
WSACleanup();
return 1;
}
if (listen(sListen, SOMAXCONN) == SOCKET_ERROR) //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Outstanding Max Connections
{
iResult = WSAGetLastError();
std::cout << "Failed to Listen, Error " << iResult << std::endl;
closesocket(sListen);
WSACleanup();
return 1;
}
SOCKET newConnection; //Socket to hold the client's connection
int iExitCode = 0;
do
{
std::cout << "Waiting for Client to Connect..." << std::endl;
int addrlen = sizeof(addr); //length of the address (required for accept call)
newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
if (newConnection == INVALID_SOCKET) //If accepting the client connection failed
{
iResult = WSAGetLastError();
std::cout << "Failed to accept a client's connection, Error " << iResult << std::endl;
iExitCode = 1;
break;
}
std::cout << "Client Connected!" << std::endl;
for (int counter = 0; counter < 100; ++counter)
{
std::string MOTD = "Hi there."; //Create buffer with message
if (!sendAll(newConnection, MOTD.c_str(), MOTD.length()+1))
{
iResult = WSAGetLastError();
std::cout << "Failed to Send, Error " << iResult << std::endl;
break;
}
}
closesocket(newConnection);
std::cout << "Client Disconnected!" << std::endl;
}
while (true);
closesocket(sListen);
WSACleanup();
return iExitCode;
}
Thank you for all the answers and comments! I solved the problem via changing the port number. Apparently, some of the port numbers are reserved so I have to assign another one.

Telnet server wont execute my command sent from a socket

Hi im currently working on a program that sends a command to the telnet server.
Here is my code:
int _tmain(int argc, _TCHAR* argv[])
{
WSAData wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
addrinfo* result;
int res = getaddrinfo("192.168.56.101", "23", &hints, &result);
if (res)
{
std::cout << "failed to getaddrinfo" << std::endl;
}
SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (connect(sock, result->ai_addr, (int)result->ai_addrlen) != SOCKET_ERROR && sock != INVALID_SOCKET)
{
std::cout << "connected";
char* buf = "md c:\\testfolder\r\n";
std::cout << send(sock, buf, sizeof("md c:\\testfolder\r\n"), 0);
const int size = 255;
char out[size];
memset(out, 0, size);
while (true)
{
res = recv(sock, out, size, 0);
std::cout << res << std::endl; // this outputs 21
}
}
else
{
std::cout << res;
}
std::cin.get();
return 0;
}
After I send the command, the telnet server should create a folder in C:\\ directory named testfolder, but its not doing it. recv() is sending me garbage values.
I have read RFC 854, but its really hard to read. So please, explain to me what I am doing wrong with my code.
There are several problems with your code. Most importantly, if getaddrinfo() fails, you are progressing to the rest of the code, which will crash since result is invalid. And also, you are ignoring the return values of send() and recv(). And you are not actually outputting the data you receive.
Try something more like this:
int _tmain(int argc, _TCHAR* argv[])
{
WSAData wsaData;
int res = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (res != 0)
{
std::cerr << "failed to init Winsock, error " << res << std::endl;
return 1;
}
addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
addrinfo* result;
res = getaddrinfo("192.168.56.101", "23", &hints, &result);
if (res != 0)
{
std::cerr << "failed to getaddrinfo, error " << res << std::endl;
WSACleanup();
return 1;
}
SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (sock == INVALID_SOCKET)
{
res = WSAGetLastError();
std::cerr << "failed to create socket, error " << res << std::endl;
freeaddrinfo(result);
WSACleanup();
return 1;
}
if (connect(sock, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
{
res = WSAGetLastError();
std::cerr << "failed to connect, error " << res << std::endl;
freeaddrinfo(result);
closesocket(sock);
WSACleanup();
return 1;
}
freeaddrinfo(result);
std::cout << "connected";
std::string cmd = "md c:\\testfolder\r\n";
const char *buf = cmd.c_str();
int size = cmd.length();
do
{
res = send(sock, buf, size, 0);
if (res == SOCKET_ERROR)
{
res = WSAGetLastError();
std::cerr << "failed to send, error " << res << std::endl;
closesocket(sock);
WSACleanup();
return 1;
}
buf += res;
size -= res;
}
while (size > 0);
char out[255];
while (true)
{
res = recv(sock, out, sizeof(out), 0);
if (res == SOCKET_ERROR)
{
res = WSAGetLastError();
std::cerr << "failed to recv, error " << res << std::endl;
closesocket(sock);
WSACleanup();
return 1;
}
if (res == 0)
{
std::cout << "disconnected" << std::endl;
break;
}
std::cout.write(out, res);
}
closesocket(sock);
WSACleanup();
return 0;
}
Now, if you are connecting to an actual Telnet server, not just an arbitrary TCP server running on the standard Telnet port, then you need to implement the actual Telnet protocol. That means handling and responding to Telnet commands (WILL, WONT, etc), negotiating Telnet options (message buffer size, charset support, etc), and so on. Everything that is described in RFC 854, and other related RFCs. It may be hard to read (not really), but you need to read and understand it. The "garbage" you receive from the server is likely not garbage at all. It is Telnet commands you are not interpreting yet.
In a nutshell, Telnet commands are escaped, so you have to process the received data byte-by-byte, and if you encounter the escape byte 0xFF then the next byte is the command type, and depending on what that command is, there may be further bytes to complete the command. Everything else that is not a command is just raw data.

getpeername sa_data

I want to get the IP address of the socket that's connected to my server socket. I've included my code.
The sa_data doesn't return char[14] of the type "xxx.xxx.xxx.xxx". Instead, it returns [11][1][xxx][xxx][xxx][xxx][][][][][][][]...[]. Can anyone help?
int InitialResult;
char SendMessage[1024];
char ReceiveMessage[1024];
WSADATA WSAData;
addrinfo Hints;
addrinfo *Result;
SOCKET ListenSocket;
SOCKET ClientSocket;
ZeroMemory(&Hints, sizeof(Hints));
Hints.ai_family = AF_INET;
Hints.ai_socktype = SOCK_STREAM;
Hints.ai_protocol = IPPROTO_TCP;
Hints.ai_flags = AI_PASSIVE;
while(1)
{
InitialResult = WSAStartup(MAKEWORD(2,2), &WSAData);
if (InitialResult != 0)
{
cout << "WSA start up failed.";
}
InitialResult = getaddrinfo(NULL, portnumber, &Hints, &Result);
if (InitialResult != 0)
{
cout << "Get address information failed.";
WSACleanup();
}
ListenSocket = socket(Result->ai_family, Result->ai_socktype, Result->ai_protocol);
if (ListenSocket == INVALID_SOCKET)
{
cout << "Socket initialization failed.";
WSACleanup();
}
InitialResult = bind(ListenSocket, Result->ai_addr, (int)Result->ai_addrlen);
if (InitialResult == SOCKET_ERROR)
{
cout << "Bind failed." << portnumber;
closesocket(ListenSocket);
ListenSocket = INVALID_SOCKET;
WSACleanup();
}
InitialResult = listen(ListenSocket, SOMAXCONN);
if (InitialResult == SOCKET_ERROR)
{
cout << "Listen failed." << portnumber;
closesocket(ListenSocket);
ListenSocket = INVALID_SOCKET;
WSACleanup();
}
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET)
{
cout << "Socket accept failed." << portnumber;
WSACleanup();
}
sockaddr test;
int a = sizeof(test);
cout << "getpeername() return value : " << getpeername(ClientSocket, &test, &a) << endl;
cout << "test.sa_data : " << test.sa_data;
StartReceive(ReceiveMessage, ClientSocket);
strcpy(SendMessage,"Congratulations!! You have successfully transfered some data to G DA.");
StartSend(SendMessage, ClientSocket);
StartSend(portnumber, ClientSocket);
InitialResult = shutdown(ClientSocket, SD_SEND);
if (InitialResult == SOCKET_ERROR)
{
cout << "Shut down failed." << portnumber;
closesocket(ClientSocket);
WSACleanup();
}
closesocket(ClientSocket);
closesocket(ListenSocket);
WSACleanup();
}
Second and third arguments of accept(2) allow you to get that information without extra call to getpeername(2). Then you need to convert binary address to string representation with something like inet_ntoa(3).
Why do you think WSADATA should be a char [14]? It's a struct as shown e.g. in these docs.
And BTW, in the various error cases you check, you should terminate the whole function (e.g. with a return), while what you're doing appears to be just to continue, after some message, with structures &c known to be invalid...
Edit: oh I see, when you say sa_data you mean test.sa_data, and another answer explained why it's not what you expect. Leaving this answer in anyway since at least the second paragraph is pretty important (and still relevant;-).
The sa_data doesn't return char[14] of
the type "xxx.xxx.xxx.xxx"
It isn't specified to do that, so no wonder it doesn't.
You need to look into sockaddr_in and sockaddr_in6.