I was not able to find what I was doing wrong on the internet.
My problem is that, recvfrom() function seems to remember the last value instead of making new calls and getting my buffer updated.
I've created the same code logic with Python and it works just find but I can't find a way to do the same in C++.
So that's my code :
#define _WINSOCKAPI_
#include <windows.h>
#include <winsock2.h>
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <time.h>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main()
{
cout << "\t\t--------------UDP Server ---------------" << endl;
cout << endl;
WSADATA WinSockData;
int iWsaStartup, iWsaCleanup;
SOCKET UDPSocketServer;
struct sockaddr_in UDPClient;
char Buffer[200];
int iBind, iReceiveFrom;
int iUDPClientLen = sizeof(UDPClient);
int iCloseSocket;
int response, offset;
ULONG cmd = 0;
iWsaStartup = WSAStartup(MAKEWORD(2, 2), &WinSockData);
if (iWsaStartup != 0) {
cout << "WSAStartup Failed" << endl;
}
cout << "WSAStartup Success" << endl;
//Setting Socket connexion information
UDPClient.sin_family = AF_INET;
UDPClient.sin_addr.s_addr = htons(INADDR_ANY);
UDPClient.sin_port = htons(40100);
//Informations to send to this address
const char* msg = "///";
size_t msg_length = sizeof(msg) - 1;
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_addr.s_addr = inet_addr("192.128.20.65");
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(40100);
//Create Socket
UDPSocketServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (UDPSocketServer == INVALID_SOCKET) {
cout << "Socket creation failed with error : " << WSAGetLastError() << endl;
WSACleanup();
exit(0);
}
cout << "Socket creation success" << endl;
//Binding Socket to INADDR_ANY 0.0.0.0:40100
iBind = bind(UDPSocketServer, (SOCKADDR*)&UDPClient, sizeof(UDPClient));
if (iBind == SOCKET_ERROR) {
cout << "Binding failed with error : " << WSAGetLastError() << endl;
closesocket(UDPSocketServer);
WSACleanup();
exit(0);
}
cout << "Binding success" << endl;
//Make sure the socket is blocking
if (ioctlsocket(UDPSocketServer, FIONBIO, &cmd) == SOCKET_ERROR) {
cout << "ioctlsocket failed with error : " << WSAGetLastError() << endl;
}
else
cout << "ioctlsocket success : " << cmd << endl; //Return 0 because it is set for Blocking
//Send information to 192.128.20.65:40100
response = sendto(UDPSocketServer, reinterpret_cast<const char*>(msg), msg_length, 0, (sockaddr*)&myaddr, sizeof(myaddr));
if (response == SOCKET_ERROR) {
cout << "Send failed with error : " << WSAGetLastError() << endl;
}
cout << "Send success : " << response << endl;
//Wait 4 seconds
Sleep(4000);
//Send information to 192.128.20.65:40100
response = sendto(UDPSocketServer, reinterpret_cast<const char*>(msg), msg_length, 0, (sockaddr*)&myaddr, sizeof(myaddr));
if (response == SOCKET_ERROR) {
cout << "Send failed with error : " << WSAGetLastError() << endl;
}
cout << "Send success : " << response << endl;
while (1) {
//Capture receive data from any address on port 40100
//This is supose to be a blocking function but it never block after the first return call
iReceiveFrom = recvfrom(UDPSocketServer, Buffer, sizeof(Buffer) + 1, MSG_PEEK, (SOCKADDR*)&UDPClient, &iUDPClientLen);
if (iReceiveFrom == SOCKET_ERROR) {
cout << "Receive failed with error : " << WSAGetLastError() << endl;
}
else if (iReceiveFrom != 0) {
Buffer[iReceiveFrom] = '\0'; //Add end of line to Buffer
//printf("%.*s\n", iReceiveFrom, Buffer);
cout << "Receive success : " << Buffer << endl;
}
}
iCloseSocket = closesocket(UDPSocketServer);
iWsaCleanup = WSACleanup();
if (iWsaCleanup == SOCKET_ERROR) {
cout << "WSA Cleanup failed with error : " << WSAGetLastError() << endl;
}
cout << "WSA Cleanup success" << endl;
system("PAUSE");
return 0;
}
I've created a UDP C++ socket that binds itself to 0.0.0.0:40100 and listens to that port using the function recvfrom().
The problem is that my recvfrom() function seems to never update or wait for new data. It just sends over the same old data without waiting.
I've tried to add some code that will change all the value of the buffer, but when recvfrom() is called the value recieved is the same as the old one.
From what I've read, recvfrom() function is supposed to be a blocking function, but in my case, it doesn't seems to work.
I've made sure the function was blocking by looking at ioctlsocket() function response; it's set to 0, so it's supposed to block.
I've also tried to create a new socket for my sendTo() function and I got the same result.
Finally, I've also tried to remove the sendTo() functions, but like my code in Python, no data seems to comeback from the socket if I don't send the string in the first place. (Wireshark shows that there's data that is sent to this port at all the time. Without this initialization, I can't get anything to print on my socket).
I find it strange that data is recieved on a certain port on my computer but when bind to that port I can't see this data before sending data to the address that send it in the first place. So I think the problem might happens between the sendTo() call and the recvfrom().
Using MSG_PEEK with recvfrom doesn't remove the data from the incoming data queue, it's still there the next time you call recvfrom.
Related
The problem seems to be in step 8. I am trying to use a while loop on the recv() function that I thought would allow me to keep appending to the RecvBuffer, but instead it just stalls and the program doesn't do anything. I am pretty sure I am missing something that would enable me to take multiple lines of input from a connected session, say, via netcat.exe for example. Any suggestions would be very welcome.
UPDATE: I made some edits, and I can now continue to input from the client connection, and these get sent, but I get weird outputs from the previous input and clearing the buffer doesn't seem to work.
The out put I get in the Server when I input "something goes here" from
cout << "Receive success: " << RecvBuffer << " ----> end of input"<<endl;
is this:
Receive success: g goes h ----> end of input
Receive success: ere
es h ----> end of input
I'm not sure why the above occurs
#include <iostream>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <Tchar.h>
#pragma warning(suppress : 4996)
using namespace std;
int main()
{
cout << "TCP SERVER" << endl;
//LOCAL VARIABLES
WSADATA Winsockdata;
int iWsaStartUp;
int iWsaCleanUp;
SOCKET TCPServerSocket;
int iCloseSocket;
struct sockaddr_in TCPServerAdd; //This is the structure
struct sockaddr_in TCPClientAdd;
int iTCPClientAdd = sizeof(TCPClientAdd);
int iBind;
int iListen;
SOCKET sAcceptSocket;
int iSend;
char SenderBuffer[512] = "Hello from server!";
int iSenderBuffer = strlen(SenderBuffer);
int iRecv;
char RecvBuffer[512] = "Input: ";
int iRecvBuffer = strlen(RecvBuffer) + 1;
int newiRecv;
char newRecvBuffer[512];
int newiRecvBuffer = strlen(newRecvBuffer) + 1;
//STEP 1: WSAStasrtup Function - initiates use of the Winsock DLL by a process
//See the MSDN for a great guite for this and ALL of the processes here-https://learn.microsoft.com/en-gb/windows/win32/winsock/initializing-winsock
//and https://learn.microsoft.com/en-gb/windows/win32/winsock/creating-a-basic-winsock-application
iWsaStartUp = WSAStartup(MAKEWORD(2, 2), &Winsockdata); //more info-https://stackoverflow.com/questions/24131843/what-is-makeword-used-for
if (iWsaStartUp != 0) {
cout << "WSAStartup FAILED" << endl;
}
else {
cout << "WSAStartup Success" << endl;
}
//STEP 2 - FILL THE STRUCTURE
TCPServerAdd.sin_family = AF_INET;
InetPton(AF_INET, _T("127.0.0.1"), &TCPServerAdd.sin_addr.s_addr);
//TCPServerAdd.sin_addr.s_addr = inet_addr("127.0.0.1"); <------- this is now depreciated, so see the above line of code
TCPServerAdd.sin_port = htons(8000);
//STEP 3: Create socket
TCPServerSocket = socket(AF_INET, SOCK_STREAM,0);
if (TCPServerSocket == INVALID_SOCKET) {
cout << "TCP Server socket gailed " << WSAGetLastError() << endl;
}
else {
cout << "TCP Server socket creation success" << endl;
}
//STEP 4: Bind
iBind = bind(TCPServerSocket, (SOCKADDR*)&TCPServerAdd, sizeof(TCPServerAdd));
if (iBind == SOCKET_ERROR) {
cout << "bind failed with " << WSAGetLastError() << endl;
}
else {
cout << "bind success" << endl;
}
//STEP 5: listen
iListen = listen(TCPServerSocket, SOMAXCONN);
if (iListen == SOCKET_ERROR) {
cout << "Listen function failed with " << WSAGetLastError() << endl;
}
else
{
cout << "Listen fucntiuon success" << endl;
}
//STEP 6: Accept
sAcceptSocket = accept(TCPServerSocket, (SOCKADDR*)&TCPClientAdd, &iTCPClientAdd);
if (sAcceptSocket == INVALID_SOCKET)
{
cout << "accept failed with " << WSAGetLastError() << endl;
}
else
{
cout << "Accept success" << endl;
}
//STEP 7: send
iSend = send(sAcceptSocket, SenderBuffer, iSenderBuffer, 0);
if (iSend == SOCKET_ERROR)
{
cout << "send failed with " << WSAGetLastError() << endl;
}
else
{
cout << "send success" << endl;
}
//STEP 8: recv
while (1) {
iRecv = recv(sAcceptSocket, RecvBuffer, iRecvBuffer, 0);
if (iRecv == SOCKET_ERROR)
{
cout << "receive failed with " << WSAGetLastError() << endl;
}
else
{
cout << "Receive success: " << RecvBuffer << " ----> end of input"<<endl;
}
char txbuf[512];
strcpy_s(txbuf, "you said: ");
strcat_s(txbuf, RecvBuffer);
send(sAcceptSocket, txbuf, strlen(txbuf) + 1, 0);
}
}
I'm trying to implement my own server and client side which uses sockets to send and receive data. But i got some problem with realization of multi-threading.
My server.cpp:
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <thread>
using namespace std;
void connection_handler(int socket) {
char client_message[256];
memset(&client_message, 0, 256);
size_t message_size = 0;
while ((message_size = recv(socket, client_message, sizeof(client_message) - 1, 0)) > 0) {
client_message[message_size] = '\0';
cout << "[Server] Client message accepted" << endl;
cout << "[Server] Client message: " << client_message << endl;
if (write(socket, client_message, message_size) == -1) {
cout << "[Client] Message sending failed" << endl;
return;
}
cout << "[Server] Message sent to client" << endl << endl;
cout << "============================" << endl << endl;
cout.flush();
memset(&client_message, 0, 256);
}
}
int main() {
unsigned short int PORT = 8080;
int listener, client_socket;
socklen_t client_len;
struct sockaddr_in server_address{};
memset(&server_address, 0, sizeof(server_address));
listener = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
if (inet_aton("127.0.0.1", &server_address.sin_addr) == 0) {
cout << "[Server] Invalid IP address" << endl;
return -1;
}
if (bind(listener, (struct sockaddr*) &server_address, sizeof(server_address)) == -1) {
cout << "[Server] Binding failed" << endl;
return -1;
}
cout << "[Server] All setting are done" << endl;
cout << "[Server] Server enabled" << endl;
if (listen(listener, 100) == -1) {
cout << "[Server] Listening failed" << endl;
return -1;
}
cout << "[Server] Waiting for connection..." << endl;
for (; ;) {
client_socket = accept(listener, (struct sockaddr*) &server_address, &client_len);
cout << "[Server] Connection accepted" << endl << endl;
cout << "----------------------------" << endl << endl;
int new_socket = client_socket;
thread handling_thread(connection_handler, new_socket);
handling_thread.detach();
}
}
My client.cpp:
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
int main() {
unsigned short int PORT = 8080;
int sockfd;
char buffer[256] = {0};
struct sockaddr_in server_address{};
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&server_address, '0', sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
server_address.sin_addr.s_addr = INADDR_ANY;
if (connect(sockfd, (struct sockaddr*) &server_address, sizeof(server_address)) < 0) {
cout << "[Client] Connection failed" << endl;
return -1;
}
cout << "[Client] All setting are done" << endl;
cout << "[Client] Succefully connected to server" << endl << endl;
cout << "----------------------------" << endl << endl;
while (true) {
string client_request;
cout << "[Client] Enter a message: ";
getline(cin, client_request);
if (client_request == "-1") {
write(sockfd, client_request.c_str(), client_request.size());
close(sockfd);
cout << endl << "[Client] Client exited" << endl;
return 0;
}
if (write(sockfd, client_request.c_str(), client_request.size()) == -1) {
cout << "[Client] Message sending failed" << endl;
}
cout << "[Client] Message sent to server" << endl;
memset(&buffer, 0, 256);
read(sockfd, buffer, 256);
cout << "[Client] Server message: " << buffer << endl << endl;
cout << "============================" << endl << endl;
cout.flush();
}
}
It's perfectly working until i create one more connection to server and after that second client cans send and receive data, but first one at this time becomes not working.
I compiled my program like this: g++ server.cpp -lpthread -o server -std=c++11 And then in other console tab run my compiled client.cpp: ./client.
To check multi-threading working i run client one more time (in other tab again) and trying send requests in two tabs at the same time.
I want to realize multi-threading in my program. How can i do this?
UPD: I'm using Linux
UPD2: Problem solved. Fixed code there.
int new_socket = client_socket;
thread handling_thread(connection_handler, &new_socket);
handling_thread.detach();
}
This initializes new_socket, which gets declared in local scope inside this for loop, then passes the pointer to this new_socket to a new thread that gets started, and detached. Immediately after that, this for loop iteration ends, which destroys the new_socket object, before starting the next iteration of this loop.
Meanwhile, the execution thread repeatedly attempts to dereference the int * it receives, which now points to a destroyed object. This results in undefined behavior, and the likely reason your program is "not working".
The most simple solution is to create the int socket value in dynamic scope, using new, and then pass the pointer to this newed socket value to the execution thread. The execution thread will, of course, be responsible for retrieving the socket value, then properly deleteing it, to avoid leaking memory.
This should be sufficient for this simple program. More complicated programs will likely require slightly more sophisticated socket and dynamic scoping handling logic, for reliability.
I have a problem with simple Winsock chat application in C++. I've written a code that enables the user to choose if he wants to send data or receive the data and depending on users choice, the appropriate functions are executed. What I would like to achieve, is that the user can BOTH send and receive data. How could I approach it? Please note that I don't want to use multiple client, I just want to send and receive data by server and send and receive data by client simultaneously.
Edit: I added my code.
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctime>
int main()
{
string IP;
int userType;
// Ask the user if he is server or client
cout << "Hi, which type of user are you? 1 - Server, 2 - Client" <<endl;
cin >> userType;
// depending on the declared user type, execute the appropriate code
if (userType == 1)
{
//initialize winsock and create a socket
WSAData wsaData; // initialize
iResult = WSAStartup(MAKEWORD(2,1), &wsaData);
if (iResult != NO_ERROR) // check for errors
cout << "Error at WSAStartup()" <<endl;
else
cout << "WSAStartup() is OK." <<endl;
// create socket
sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
if (sockSocket == INVALID_SOCKET) // check for errors
{
cout << "Error at socket(): " << WSAGetLastError();
WSACleanup();
return true;
}
else
cout << "Socket() is OK." <<endl;
return true;
// bind to socket
service.sin_addr.s_addr = inet_addr("0.0.0.0");
service.sin_family = AF_INET;
service.sin_port = htons(55555);
if (bind(sockSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) // cheking for errors
{
cout << "Bind() failed." << endl;
closesocket(sockSocket);
return true;
}
else
cout << "Bind() is OK." <<endl;
// listen
listen(sockSocket, SOMAXCONN);
if (listen(sockSocket, 10) == SOCKET_ERROR) // check for errors
{
cout << "Error listening on socket." << endl;
return true;
}
else
cout << "Listen() is OK." <<endl;
//accept connection
servlen = sizeof(service);
cout << "Waiting for user to connect..." << endl;
acceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(acceptSocket = accept(sockSocket, (SOCKADDR*)&service, &servlen))
{
cout << "A coonnection was found" <<endl<<endl;
}
sockSocket = acceptSocket;
// receive messages
do
{
std::string message;
char Buffer[512];
iResult = recv(sockSocket, Buffer, 512, 0);
Buffer[iResult] = '\0';
message = Buffer;
currentDate();
std::cout << Buffer <<endl<<endl;
}while(iResult>0);
closesocket(sockSocket);
WSACleanup();
}
else if (userType == 2)
{
// exactly the same code as for server part to initialize and create socket
// ask for the ip the user wants to connect to
cout << "Hi what's the IP that you want to connect to?" <<endl;
cin >> IP;
// connect to socket
conService.sin_addr.s_addr = inet_addr(IP); // connect to the ipnuted IP
conService.sin_family = AF_INET;
conService.sin_port = htons(55555); // should the port also be the argument?
if (connect(sockSocket, (SOCKADDR*)&conService, sizeof(conService)) == SOCKET_ERROR) // check for errors
{
cout << "Failed to connect: " << WSAGetLastError();
WSACleanup();
return true;
}
else
{
cout << "Connected." <<endl;
}
// send messages
for (;;)
{
std::string message;
std::getline(std::cin, message);
unsigned int Length = strlen(message.c_str());
if(Length>512)
Length = 512;
currentDate();
iResult = send(sockSocket, message.c_str(),Length,0);
}
closesocket(sockSocket);
WSACleanup();
}
WSACleanup();
return 0;
}
Edit2: As Lemy suggested in the comment, I need to have a second thread (as the first one is simply what's going on in the main function). From what I understood, I can use CreateThread function. My problem of how to both send and receive messages is solved (I should create another thread), but now I have problem with implementing the solution. As I wrote in the comment below Lemy's answer, I get such error referring to the line where I use CreateThread function (HANDLE hThread = CreateThread(0,0,&ReadingThread,acceptSocket,0,&dwThreadID);):
invalid conversion from 'SOCKET {aka unsigned int}' to 'PVOID {aka void*}' [-fpermissive]| and
invalid conversion from 'DWORD {aka long unsigned int}' to 'PDWORD {aka long unsigned int*}' [-fpermissive]
Any hints for that? Hope this makes my question more specific(if not pls tell me what should I specify more).
You need to have the client and server continuously reading in the background for the lifetime of the connection, and then they can send data in parallel whenever needed. Move your reading logic into a separate thread, eg:
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctime>
DWORD WINAPI ReadingThread(LPVOID param)
{
SOCKET s = (SOCKET) param;
char Buffer[512];
int iResult;
do
{
iResult = recv(s, Buffer, 512, 0);
if (iResult <= 0) break;
Buffer[iResult] = '\0';
std::cout << "Recv: " << message << std::endl;
}
while (true);
return 0;
}
int main()
{
int userType;
HANDLE hThread;
DWORD dwThreadID;
//initialize winsock and create a socket
WSAData wsaData; // initialize
iResult = WSAStartup(MAKEWORD(2,1), &wsaData);
if (iResult != NO_ERROR) // check for errors
{
std::cout << "Error at WSAStartup()" << std::endl;
return 0;
}
std::cout << "WSAStartup() is OK." << std::endl;
// Ask the user if he is server or client
std::cout << "Hi, which type of user are you? 1 - Server, 2 - Client" << std::endl;
std::cin >> userType;
// depending on the declared user type, execute the appropriate code
if (userType == 1)
{
// create socket
sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
if (sockSocket == INVALID_SOCKET) // check for errors
{
std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
WSACleanup();
return 0;
}
std::cout << "Socket() is OK." << std::endl;
// bind to socket
service.sin_addr.s_addr = INADDR_ANY;
service.sin_family = AF_INET;
service.sin_port = htons(55555);
if (bind(sockSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) // cheking for errors
{
std::cout << "Error at bind(): " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
std::cout << "Bind() is OK." << std::endl;
// listen
if (listen(sockSocket, 10) == SOCKET_ERROR) // check for errors
{
std::cout << "Error at listen(): " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
std::cout << "Listen() is OK." << std::endl;
//accept connection
servlen = sizeof(service);
std::cout << "Waiting for user to connect..." << std::endl;
acceptSocket = accept(sockSocket, (SOCKADDR*)&service, &servlen);
if (acceptSocket != INVALID_SOCKET)
{
std::cout << "Error at accept(): " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
std::cout << "A client has connected" << std::endl << std::endl;
// receive messages
hThread = CreateThread(NULL, 0, &ReadingThread, (void*)acceptSocket, 0, &dwThreadID);
if (!hThread)
{
std::cout << "Error at CreateThread(): " << GetLastError() << std::endl;
closesocket(acceptSocket);
closesocket(sockSocket);
WSACleanup();
return 0;
}
// send messages
do
{
std::string message;
if (!std::getline(std::cin, message))
break;
if (send(acceptSocket, msg.c_str(), msg.length(), 0) == SOCKET_ERROR)
{
std::cout << "Error at send(): " << WSAGetLastError() << std::endl;
break;
}
}
while (true);
closesocket(acceptSocket);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
closesocket(sockSocket);
WSACleanup();
}
else if (userType == 2)
{
// create socket
sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
if (sockSocket == INVALID_SOCKET) // check for errors
{
std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
WSACleanup();
return 0;
}
std::cout << "Socket() is OK." << std::endl;
// ask for the ip the user wants to connect to
std::string IP;
std::cout << "Hi what's the IP that you want to connect to?" << std::endl;
std::cin >> IP;
// connect to socket
conService.sin_addr.s_addr = inet_addr(IP.c_str()); // connect to the ipnuted IP
conService.sin_family = AF_INET;
conService.sin_port = htons(55555); // should the port also be the argument?
if (connect(sockSocket, (SOCKADDR*)&conService, sizeof(conService)) == SOCKET_ERROR) // check for errors
{
std::cout << "Failed to connect: " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
std::cout << "Connected." << std::endl;
// receive messages
hThread = CreateThread(NULL, 0, &ReadingThread, (void*)sockSocket, 0, &dwThreadID);
if (!hThread)
{
std::cout << "Error at CreateThread(): " << GetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}
// send messages
do
{
std::string message;
if (!std::getline(std::cin, message))
break;
if (send(sockSocket, msg.c_str(), msg.length(), 0) == SOCKET_ERROR)
{
std::cout << "Error at send(): " << WSAGetLastError() << std::endl;
break;
}
}
while (true);
closesocket(sockSocket);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
WSACleanup();
}
else
{
std::cout << "Invalid type entered!" << std::endl;
WSACleanup();
return 0;
}
return 0;
}
I am learning socket programming for use in an upcoming project, and I have researched the issue pretty extensively. Basically, all this program needs to is on a client computer (locally, i.e. my computer) needs to connect to a remote server and send a command (which it has done, I have gotten it to read back Apache server stats to me).
What is happening is this: I believe I have the socket set right, but the server receives random garbage buffers (one of which consisted of " '>Z"). I have tried various socket settings, different bindings, etc.
I have in the process of starting it will initialize winsock, create a socket, bind the network, and then do a listen loop and while(1) recv data.
I have yet to get the server (on a remote computer, hosted at a datacenter) to output the message. This is my only goal for the time being. I appreciate everyone's help in advance, and the code is before (this is the entire code, sorry for the length).
Client Code:
char *host = "127.0.0.1";
SOCKET clientsock;
struct sockaddr_in server_address;
struct hostent *host_info;
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData) != -1) {
cout << "WINSOCK2 Initialized" << endl;
if((clientsock = socket(AF_INET, SOCK_STREAM, 0)) != SOCKET_ERROR) {
cout << "Socket Created" << endl;
char opt[2];
opt[0] = 0;
opt[1] = 1;
//setsockopt(clientsock, SOL_SOCKET, SO_BROADCAST, opt, sizeof(opt));
host_info = gethostbyname(host);
server_address.sin_family = AF_INET;
server_address.sin_addr = *((struct in_addr *)host_info->h_addr);
server_address.sin_port = htons(80);
if(connect(clientsock, (struct sockaddr *)&server_address, sizeof(struct sockaddr)) == 0) {
cout << "Connected to host" << endl;
char COMMAND[22] = "SVR --WINSOCK-VERIFY\0";
if(send(clientsock, COMMAND, sizeof(COMMAND), 0)) {
cout << "Command Sent" << endl;
closesocket(clientsock);
}
else {
cout << "ERROR - Could not send command. " << "Error: " << WSAGetLastError() << endl;
closesocket(clientsock);
WSACleanup();
}
}
else {
cout << "ERROR - Could not connect to host. " << "Error: " << WSAGetLastError() << endl;
closesocket(clientsock);
WSACleanup();
}
}
else {
cout << "ERROR - Could not create the socket. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
}
else {
cout << "ERROR - Could not initialize WINSOCK2. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
Server Code:
SOCKET serversock;
char *server = "127.0.0.1";
//char *server = "50.31.1.180";
struct sockaddr_in server_address;
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData) != -1) {
cout << "WINSOCK2 Initialized" << endl;
if((serversock = socket(PF_INET, SOCK_DGRAM, PF_UNSPEC)) != SOCKET_ERROR) {
cout << "Socket Created" << endl;
unsigned long NB = 1;
ioctlsocket(serversock, FIONBIO, &NB);
server_address.sin_family = AF_INET;
server_address.sin_addr = *((struct in_addr *)server);
server_address.sin_port = htons(21578);
if(bind(serversock, (struct sockaddr*)&server_address, sizeof(struct sockaddr) == 0)) {
cout << "Network bound" << endl;
cout << "Listening..." << endl;
listen(serversock, 5);
while(1) {
int size = sizeof((struct sockaddr *)server);
SOCKET clientsock = accept(serversock, (struct sockaddr *)server, &size);
char INCOMMAND[20];
if(clientsock >= 0) {
if(recv(clientsock, INCOMMAND, sizeof(INCOMMAND), 0)) {
int i = 0;
if(INCOMMAND == "SVR --WINSOCK-VERIFY\0") {
cout << "SVR receieved" << endl;
}
while(INCOMMAND[i] != '\0') {
cout << INCOMMAND[i];
i++;
}
cout << endl;
}
else {
cout << "ERROR - Could not receive command" << endl;
break;
}
}
}
}
else {
cout << "ERROR - Could not bind network. " << "Error: " << WSAGetLastError() << endl;
closesocket(serversock);
WSACleanup();
}
}
else {
cout << "ERROR - Could not create the socket. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
}
else {
cout << "ERROR - Could not initialize WINSOCK2. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
Calls to send/recv may not send/receive the amount of bytes you indicate in their third argument, in fact, most of the time they will send/receive less bytes than you expect. You usually have to loop until the entire data has been sent/received. Also note that doing this:
char buffer[100];
recv(clientsock, buffer, sizeof(buffer), 0);
cout << buffer;
Will most surelly print garbage, since you don't have a null terminator in your char array(whatch out for buffer overflows when appending it), and you're not checking the return value of recv. It might be reading 1 byte only(or none if an error ocurred). You're printing your buffer the same way in your server app.
In this case, you are actually sending the null-terminator, but since you might read less bytes than you expect, this character might not be received by the other application, thus printing it will print garbage chars.
Edit: You should have a look at the structure of a sockaddr struct. You can have a look at it here. In your code you are using this convertion:
int size = sizeof((struct sockaddr *)"127.0.0.1");
const char *, which is the type of "127.0.0.1", cannot be casted to a sockaddr pointer, they're incompatible. Here you should use getaddrinfo in order to resolve the IP address(note that you could use a domain name, and this function would resolve it). There are lots of tutorials online on how to use this function, just search for "getaddrinfo".
I'm trying to make a simple chat program between to programs on a lan. My problem is I can easily connect and send message from the server to client but not the other way around. I'm trying to make it work like this. Server<->Client as in constantly sending and receiving between both programs, obviously that would require a loop for continuous input but I'm not quite sure how to do it. Here is the code for both server and client.
//THIS IS THE SERVER
int main(int argc, char *argv[])
{
WSADATA wsaData;
int starterr = WSAStartup(MAKEWORD(2,2), &wsaData);
if (starterr != 0)
{
cout << "WSADATA Failed to startup!" << endl;
cout << "Error Code: " << WSAGetLastError() << endl;
system("pause >nul");
WSACleanup();
return 0;
}
cout << "WSADATA Startup Successful!" << endl;
SOCKET mysock = socket(AF_INET, SOCK_STREAM, 0);
if (mysock == INVALID_SOCKET)
{
cout << "Socket Creation Failed!" << endl;
cout << "Error Code: " << WSAGetLastError() << endl;
system("pause >nul");
WSACleanup();
return 0;
}
cout << "Socket Creation Successful!" << endl;
sockaddr_in sin;
sin.sin_port = htons(80);
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_family = AF_INET;
if (bind(mysock,(sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
{
cout << "Socket failed to bind!" << endl;
cout << "Error Code: " << WSAGetLastError() << endl;
system("pause >nul");
WSACleanup();
return 0;
}
cout << "Socket Binded Successfuly!" << endl;
//Listen to the socket until successful on receiving input
while (listen(mysock, SOMAXCONN) == SOCKET_ERROR);
SOCKET client;
int lin = sizeof(sin);
client = accept(mysock,(sockaddr*) &sin, &lin);
cout << "Connection Established!" << endl;
char buf[200] = "Message from server to client\n";
//Send an initial message to the client
send(client, buf, sizeof(buf), 0);
//but then how do I wait for a message from the client again here??
//ive tried recv here before with no luck :/
closesocket(mysock);
closesocket(client);
WSACleanup();
system("pause >nul");
return 0;
}
//Client program here
int main(int argc, char *argv[])
{
WSADATA wsaData;
int starterr = WSAStartup(MAKEWORD(2,2), &wsaData);
if (starterr != 0)
{
cout << "WSADATA startup has failed!" << endl;
cout << "Error Code: " << WSAGetLastError() << endl;
system("pause >nul");
WSACleanup();
return 0;
}
cout << "WSADATA Startup Successful!" << endl;
SOCKET mysock = socket(AF_INET, SOCK_STREAM, 0);
if (mysock == INVALID_SOCKET)
{
cout << "Socket Creation Failed!" << endl;
cout << "Error Code: " << WSAGetLastError() << endl;
system("pause >nul");
WSACleanup();
return 0;
}
cout << "Socket Creation Successful!" << endl;
sockaddr_in sin;
sin.sin_port = htons(80);
sin.sin_addr.s_addr = inet_addr("127.0.0.1");//ip for connection
sin.sin_family = AF_INET;
if (connect(mysock,(sockaddr*)&sin, sizeof(sin)) == INVALID_SOCKET)
{
cout << "Socket Connection Failed" << endl;
cout << "Error Code: " << WSAGetLastError() << endl;
system("pause >nul");
closesocket(mysock);
WSACleanup();
return 0;
}
cout << "Socket Has Connected Successfuly!" << endl;
//Same applies here, receive message but exactly how do I send one back
char buf[200];
recv(mysock, buf, sizeof(buf), 0);
cout << buf;
//send here seemed to bring up a bunch of symbols
system("pause >nul");
WSACleanup();
closesocket(mysock);
return 0;
}
If you want full-duplex communication (i.e. both server and client sides able to send and receive at any time), you can either use multiple threads (which I don't recommend, since multithreading introduces race conditions and deadlocks unless you really know what you are doing), or use non-blocking I/O, multiplexed using select() or poll() or similar. With multiplexing, you basically tell the select()/poll() call "don't return until something interesting happens", where "something interesting" is defined as "data arrived on a socket", or (if you have data to send) "there is now buffer space available on a socket to place some outgoing data into". Then when select()/poll() returns, you examine what events have been flagged as ready, call send()/recv() as appropriate (these calls won't ever block since you set the sockets to non-blocking-I/O mode), and then go back to sleep inside select()/poll() again until the next events occur.
In this way your program is able to handle both send() and recv() efficiently, without spinning the CPU and without every having recv() hold off send() (or vice versa).
take a look at here:
Client-Server communiation
But also you have to be familiar with multithreading, because in this link-example you have infinite loops in client and server examples that listens for incoming messages, so you have to put them in thread and you will be able to send and listen messages asynchronously. If you don't put them in thread you won't be able to send and receive messages asynchronously, because infinite loops block all operations beyond them.
I think this is the most simpliest way to establish communication.