Problems intercommunicating processes in c++ using winsock2 - c++

I am having terrible trouble intercommunicating processes, using UNIX sockets. My server is written in c++, but I can't get past calling the bind method.
c++ code.
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Entry"));
WCHAR strbuf[256];
WSADATA wsaData;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
wsprintfW(strbuf, L"My Sample Service : WSAStartup failed with error: %d", iResult);
OutputDebugString(strbuf);
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));
return 1;
}
int opt = TRUE;
int master_socket, addrlen, new_socket, client_socket[30],
max_clients = 30, activity, i, valread, sd;
int max_sd;
struct sockaddr_in address;
char buffer[1025]; //data buffer of 1K
//set of socket descriptors
fd_set readfds;
TIMEVAL tv = { 2, 0 };
//a message
char *message = "ECHO Daemon v1.0 \r\n";
//initialise all client_socket[] to 0 so not checked
for (i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
/*struct addrinfo *result = NULL;
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNIX;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
hints.ai_flags = AI_PASSIVE;
iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
wsprintfW(strbuf, L"My Sample Service : getaddrinfo failed with error: %d", iResult);
OutputDebugString(strbuf);
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit 2"));
WSACleanup();
return 1;
}*/
//create a master socket
if ((master_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == 0)
{
OutputDebugString(_T("My Sample Service : socket failed with error"));
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));
return 1;
}
//set master socket to allow multiple connections ,
//this is just a good habit, it will work without this
if (setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
sizeof(opt)) < 0)
{
OutputDebugString(_T("My Sample Service : setsockopt failed with error"));
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));
return 1;
}
//type of socket created
address.sin_family = AF_UNIX;
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //I really don't know what to put here
//address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
////bind the socket to localhost port 8000
//if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0)
//{
// wsprintfW(strbuf, L"My Sample Service : bind failed with error: %d", WSAGetLastError());
// OutputDebugString(strbuf);
// OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit 2"));
// closesocket(master_socket);
// WSACleanup();
// return 1;
//}
// Setup the TCP listening socket
iResult = bind(master_socket, (struct sockaddr *)&address, sizeof(address));
if (iResult == SOCKET_ERROR) {
wsprintfW(strbuf, L"My Sample Service : bind failed with error: %d", WSAGetLastError());
OutputDebugString(strbuf);
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));
closesocket(master_socket);
WSACleanup();
return 1;
}
//freeaddrinfo(result);
//try to specify maximum of 3 pending connections for the master socket
if (listen(master_socket, 3) < 0)
{
wsprintfW(strbuf, L"My Sample Service : listen failed with error: %d\n", WSAGetLastError());
OutputDebugString(strbuf);
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));
closesocket(master_socket);
WSACleanup();
return 1;
}
addrlen = sizeof(address);
//accept the incoming connection
wsprintfW(strbuf, L"My Sample Service : Listener on port %d", PORT);
OutputDebugString(strbuf);
OutputDebugString(_T("My Sample Service: Waiting for connections ..."));
// Periodically check if the servC:\Users\Administrator\Desktopice has been requested to stop
while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
{
/*
* Perform main service function here
*/
//clear the socket set
FD_ZERO(&readfds);
//add master socket to set
FD_SET(master_socket, &readfds);
max_sd = master_socket;
//add child sockets to set
for (i = 0; i < max_clients; i++)
{
//socket descriptor
sd = client_socket[i];
//if valid socket descriptor then add to read list
if (sd > 0)
FD_SET(sd, &readfds);
//highest file descriptor number, need it for the select function
if (sd > max_sd)
max_sd = sd;
}
//wait for an activity on one of the sockets , timeout is NULL ,
//so wait indefinitely
activity = select(max_sd + 1, &readfds, NULL, NULL, &tv);
if ((activity < 0) && (errno != EINTR))
{
OutputDebugString(_T("My Sample Service: select failed with error"));
}
//If something happened on the master socket ,
//then its an incoming connection
if (FD_ISSET(master_socket, &readfds))
{
if ((new_socket = accept(master_socket,
(struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
wsprintfW(strbuf, L"My Sample Service : accept failed with error: %d", WSAGetLastError());
OutputDebugString(strbuf);
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));
closesocket(master_socket);
WSACleanup();
return 1;
}
//inform user of socket number - used in send and receive commands
wsprintfW(strbuf, L"My Sample Service : New connection , socket fd is %d , ip is : %s , port : %d" , new_socket , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
OutputDebugString(strbuf);
//send new connection greeting message
if (send(new_socket, message, strlen(message), 0) != strlen(message))
{
OutputDebugString(_T("My Sample Service: Welcome message sent failed with error"));
}
else
{
OutputDebugString(_T("My Sample Service: Welcome message sent successfully"));
}
//add new socket to array of sockets
for (i = 0; i < max_clients; i++)
{
//if position is empty
if (client_socket[i] == 0)
{
client_socket[i] = new_socket;
wsprintfW(strbuf, L"My Sample Service: Adding to list of sockets as %d", i);
OutputDebugString(strbuf);
break;
}
}
}
//else its some IO operation on some other socket
for (i = 0; i < max_clients; i++)
{
sd = client_socket[i];
if (FD_ISSET(sd, &readfds))
{
//Check if it was for closing , and also read the
//incoming message
if ((valread = recv(sd, buffer, 1024, 0)) == 0)
{
//Somebody disconnected , get his details and print
getpeername(sd, (struct sockaddr*)&address, \
(socklen_t*)&addrlen);
wsprintfW(strbuf, L"My Sample Service: Host disconnected , ip %s , port %d",
inet_ntoa(address.sin_addr), ntohs(address.sin_port));
OutputDebugString(strbuf);
//Close the socket and mark as 0 in list for reuse
closesocket(sd);
client_socket[i] = 0;
}
//Echo back the message that came in
else
{
//set the string terminating NULL byte on the end
//of the data read
buffer[valread] = '\0';
send(sd, buffer, strlen(buffer), 0);
}
}
}
}
The error returned by the bind method is 10022. I only want to accept connections from my own machine. The commented part of the code is because somewhere, I read that for UNIX sockets, getaddrinfo should not be done. Can someone help me to solve my problem??
I can't find any complete example project of process intercommunication using winsock either, if you point me to one it would also be very helpful.
THANK
EDIT
I am trying to intercommunicate two processes in windows. The link left by #Hans_Passant in the comments, points out that for this I must Download the Windows Insiders SDK for the Windows build 17061, but it is not available to everyone, it says: "To access this page, you need to be a member of the Windows Insider Program". so how can I do it?

Unix sockets are already local, you must put nothing but the address family in the address:
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sun_family = AF_UNIX;
Example (source: doc):
int sfd, cfd;
struct sockaddr_un my_addr, peer_addr;
socklen_t peer_addr_size;
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd == -1)
handle_error("socket");
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sun_family = AF_UNIX;
strncpy(my_addr.sun_path, MY_SOCK_PATH,
sizeof(my_addr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &my_addr,
sizeof(my_addr)) == -1)
handle_error("bind");
if (listen(sfd, LISTEN_BACKLOG) == -1)
handle_error("listen");
/* Now we can accept incoming connections one
at a time using accept(2). */
peer_addr_size = sizeof(peer_addr);
cfd = accept(sfd, (struct sockaddr *) &peer_addr,
&peer_addr_size);
Update: I would recommend you to stick to TCP sockets:
master_socket = socket(AF_INET, SOCK_STREAM, 0)
and then:
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_LOOPBACK;
address.sin_port = htons(PORT);
Listening in the loopback interface ensures that no connections from the outside world will ever reach the socket.

Related

C++ TCP Server (Winsock) Connecting (invalid client) Instantly Then Closes

Edit: Working on a solution - turns out googling 204.204.204.204 gets me further than more descriptive requests.
Honestly. Wits end. I have no idea how I can spend an entire day doing something that took 10 minutes in Flask (Server) and Javascript (client). I need this to run in C++ and allow a client to connect via BlueStacks' port on the same machine. The client is unimportant because I can't even get that far.
I've tried WinSocks, I've tried WxWidget's networking implementation, I've even tried some random C++ wrapper thing. All of them failed (typically within the EXAMPLE! As in, copy paste and errors everywhere). So I ultimately went back to WinSockets and followed a tutorial on YouTube.
int ServerStuff() {
WSADATA WsData;
WORD ver = MAKEWORD(2, 2);
int wsOK = WSAStartup(ver, &WsData);
if (wsOK != 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
return false;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Quitting");
return false;
}
//Bind the ip and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; //Could also use inet_pton
bind(listening, (sockaddr*)&hint, sizeof(hint));
//Tell winsock the socket is for listening
listen(listening, SOMAXCONN);
//Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
//if (clientSocket == INVALID_SOCKET) {
// wxLogMessage("Client Invalid Socket");
// return false;
//}
char host[NI_MAXHOST]; //Client's remote name
char service[NI_MAXHOST]; //Service (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_MAXSERV, 0) == 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
}
else {
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
wxLogMessage(host);
int wut = client.sin_port;
wxString mystring = wxString::Format(wxT("%i"), wut);
wxLogMessage("Connected on port");
wxLogMessage(mystring);
//wxLogMessage(to_string(ntohs(client.sin_port)));
}
wxLogMessage("Got this far somehow");
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//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) {
//wxLogMessage("ERROR in recv");
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
send(clientSocket, buf, bytesReceived + 1, 0);
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
ServerStuff();
//Close(true);
}
On the YouTube video ("Creating a TCP Server in C++" - not allowed to post links) this works! The command window opens, is blank infinitely until he connects a client and then the client sends a message and the server replies with the same exact message in return.
Not mine. Mine just rushes through everything and then closes. My log used to immediately quit on the commented code where it states the client socket is invalid so I commented it out. Now my output is:
204.204.204.204
Connected on port
52428
Got this far somehow
I don't know what to do. I'm just trying to send data over a same-machine TCP connection. I'm baffled as to how this is so difficult. It seems like some random process is immediately trying to connect as a client to my server ? But why is it allowed to connect on port 52428 when I'm explicitly hosting on 54000?
My goal:
Start Server
Connect to Server using a Java App within BlueStacks
Send data from Server to Client
It makes more sense for the computer to be the server because there will be multiple BlueStacks instances and I'd prefer to not have to "spawn" multiple programs / servers for what I'm doing.
I see a few mistakes in your socket code.
not calling WSACleanup() if WSAStartup() is successful and then something goes wrong afterwards.
not calling closesocket() if socket() is successful and then something goes wrong afterwards.
not zeroing out the sockaddr_in that you pass to bind(). Random bytes in the struct can cause bind() to fail.
ignoring the return values of bind(), listen(), accept(), and send().
not treating the return value of getnameinfo() correctly. It returns 0 on success, not failure.
sending +1 extra byte back to the client than you received from the client. If the client sends fewer bytes than your buffer can hold, that extra byte would be 0x00 due to your ZeroMemory() call. But if the client actually sends enough bytes to completely fill your buffer, then you would send an extra byte from memory that you do not own. If you really want to send a null terminator after everything you echo, do so explicitly. Otherwise, a true echo server should only send back exactly what it receives, no more, no less.
Try something more like this:
void ServerStuff() {
WSADATA WsData;
int ret = WSAStartup(MAKEWORD(2, 2), &WsData);
if (ret != 0) {
wxLogMessage("Can't initialize Winsock! Error: %d", ret);
return;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Error: %d", WSAGetLastError());
WSACleanup();
return;
}
//Bind the ip and port to a socket
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.s_addr = INADDR_ANY; //Could also use inet_pton
ret = bind(listening, (sockaddr*)&hint, sizeof(hint));
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't bind socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Tell winsock the socket is for listening
ret = listen(listening, SOMAXCONN);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't listen on socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Wait for a connection
sockaddr_in client = {};
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET) {
wxLogMessage("Can't accept a client! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
char host[NI_MAXHOST] = {}; //Client's remote name
ret = getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, NULL, 0, 0);
if (ret != 0) {
wxLogMessage("Can't get client name info! Error: %d", ret);
inet_ntop(AF_INET, &(client.sin_addr), host, NI_MAXHOST);
}
wxLogMessage("Client: %s, Connected on port: %hu", host, ntohs(client.sin_port));
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//while loop: accept and echo message back to client
char buf[4096];
int bytesReceived;
while (true)
{
//Wait for client to send data
bytesReceived = recv(clientSocket, buf, sizeof(buf), 0);
if (bytesReceived == SOCKET_ERROR) {
wxLogMessage("Can't read from client! Error: ", WSAGetLastError());
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
ret = send(clientSocket, buf, bytesReceived, 0);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't send to client! Error: ", WSAGetLastError());
break;
}
}
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}

Non-IOCP client send/recv error with IOCP server

Please understand that I am new to IOCP and my code may not be so perfect.
I tried many examples from around here, neither one helps me.
My actual problem is in the client side, I have no idea if I am connecting properly to a IOCP server, neither if I send the data properly and recv gives me WSAerror 10038 ...
WSADATA wsd;
struct addrinfo *result = NULL, *ptr = NULL, hints;
WSAOVERLAPPED RecvOverlapped;
SOCKET ConnSocket = INVALID_SOCKET;
WSABUF DataBuf;
DWORD RecvBytes, Flags;
CRITICAL_SECTION criti;
char buffer[DATA_BUFSIZE];
int err = 0;
int rc;
// Load Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsd);
if (rc != 0) {
return 1;
}
// Make sure the hints struct is zeroed out
SecureZeroMemory((PVOID)& hints, sizeof(struct addrinfo));
// Initialize the hints to retrieve the server address for IPv4
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
rc = getaddrinfo(IP, Port, &hints, &result);
if (rc != 0) {
return 1;
}
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
if ((ConnSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol)) == INVALID_SOCKET){
freeaddrinfo(result);
return 1;
}
rc = connect(ConnSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (rc == SOCKET_ERROR) {
if (WSAECONNREFUSED == (err = WSAGetLastError())) {
closesocket(ConnSocket);
ConnSocket = INVALID_SOCKET;
continue;
}
freeaddrinfo(result);
closesocket(ConnSocket);
WSACleanup();
return 1;
}
break;
}
if (ConnSocket == INVALID_SOCKET) {
freeaddrinfo(result);
return 1;
}
int nZero = 0;
// Make sure the RecvOverlapped struct is zeroed out
SecureZeroMemory((PVOID)& RecvOverlapped, sizeof(WSAOVERLAPPED));
// Create an event handle and setup an overlapped structure.
RecvOverlapped.hEvent = WSACreateEvent();
if (RecvOverlapped.hEvent == NULL) {
freeaddrinfo(result);
closesocket(ConnSocket);
return 1;
}
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
// send data to server here?
// removed the packets, it`s not supposed to be public
// Call WSARecv until the peer closes the connection
// or until an error occurs
while (1) {
Flags = 0;
RecvBytes = 0;
rc = WSARecv(ConnSocket, &DataBuf, 1, &RecvBytes, &Flags, &RecvOverlapped, NULL);
if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) {
closesocket(ConnSocket);
break;
}
rc = WSAWaitForMultipleEvents(1, &RecvOverlapped.hEvent, TRUE, INFINITE, TRUE);
if (rc == WSA_WAIT_FAILED) {
break;
}
rc = WSAGetOverlappedResult(ConnSocket, &RecvOverlapped, &RecvBytes, FALSE, &Flags);
if (rc == FALSE) {
break;
}
// here I have a protocol where I read the received data
WSAResetEvent(RecvOverlapped.hEvent);
// If 0 bytes are received, the connection was closed
if (RecvBytes == 0)
break;
}
WSACloseEvent(RecvOverlapped.hEvent);
closesocket(ConnSocket);
freeaddrinfo(result);
WSACleanup();
I expect to be able to send data and receive the response from IOCP, but if I send 3 packets, I receive back 2 only or sometimes even 1, when I am sending 3 packets back.
Can some show me a working example to connect and send+recv data to a IOCP server?
Many thanks!
You're using TCP. TCP is a stream protocol, not a datagram protocol. You cannot tell it what packets to send, and it cannot tell you what packets it received (it doesn't even know because that's handled at the IP layer). It just doesn't work that way.
This sentence is packed with wisdom: "TCP is a bidirectional, connection oriented, byte stream protocol that provides reliable, ordered delivery but does not preserve application message boundaries." Punch "TCP" into your favorite search engine and study until you understand precisely what every word in that sentence means. You will never write reliable, or even correct, TCP code until you do.
Whether the server is using IOCP or some other internal architecture has no effect on clients. That's totally invisible.

Unable to Send data from Server to client on local network in C++

I need to communicate between two systems on local server. So, I decided to use "Socket" programming in C++. For this I follow this tutorial. I make some changes according to my need like changing port no, IP etc which are working fine. Now the problem is I can send data from Server to Client but I am unable to receive any data from Client to Server.
Here is my code for Client:-
int main()
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
char *message , server_reply[2000];
int recv_size;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
server.sin_addr.s_addr = inet_addr("192.168.1.4");
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );
//Connect to remote server
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected");
if((recv_size = recv(s , server_reply , 2000 , 0)) == SOCKET_ERROR)
{
puts("recv failed");
}
puts("Reply received\n");
server_reply[recv_size] = '\0';
puts(server_reply);
message = "Cleint says:- I am Client";
if( send(s , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
puts("sending data complete\n");
system("pause");
return 0;
}
Here is My code for Server:-
int main()
{
WSADATA wsa;
SOCKET s , new_socket;
struct sockaddr_in server , client;
int c;
char *message , cleint_reply[2000];
int recv_size;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//Listen to incoming connections
listen(s , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while( (new_socket = accept(s , (struct sockaddr *)&client, &c)) != INVALID_SOCKET )
{
puts("Connection accepted");
//Reply to the client
message = "Server sends:- I am Server\n";
send(new_socket , message , strlen(message) , 0);
while(1)
{
if((recv_size = recv(s , cleint_reply , 2000 , 0)) == SOCKET_ERROR)
{
// puts("recv failed");
}
else
puts("data received");
}
}
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d" , WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
This is the console messages I am getting on Client:-
Initialising Winsock...
Initialised
Connected
Server sends:- I am server
Sending Data complete
Press any key to continue
And these are the messages I am getting on Server console:-
Initialising Winsock...
Socket Created
Bind Done
Waiting for incoming connections..
Connection accepted
So, please tell we why my server is not able to receive any thing...
Found the error.
Once you use accept() you have a new file descriptor which you need to use send and receive data [lets say for that specific CLIENT].
The accept() function shall extract the first connection on the queue of pending connections, create a new socket with the same socket type protocol and address family as the specified socket, and allocate a new file descriptor for that socket.
In your server when you get a new connection you correctly use new file descriptor recv_size to send data but you do not use that new connection's file descriptor to receive data.
Wrong code line
if((recv_size = recv(s , cleint_reply , 2000 , 0)) == SOCKET_ERROR)
Correction
if((recv_size = recv(new_socket , cleint_reply , 2000 , 0)) == SOCKET_ERROR)
this should work now

Writing Client and Server, UDP

I'm trying to write a simple client and server using UDP.
I can send data from the client to the server, and the server recieves it well, but when I send the data from the server to the client, it doesnt work at all...
(It doesnt detect anything, and is stuck on recvfrom function..
Here is my Server code :
SOCKET ServerOn()
{
SOCKET ListenSocket;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
exit(0);
}
// Create a SOCKET for listening for
// incoming connection requests.
ListenSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ListenSocket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("0.0.0.0");
service.sin_port = htons(2583);
if (bind(ListenSocket,(SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR)
{
closesocket(ListenSocket);
WSACleanup();
exit(2);
}
return ListenSocket;
}
In this function, I'm initializing the server on port 2583.
Here is my other code in the server :
int size = sizeof(service);
char *data = new char[500];
recvfrom(s,data, 500, NULL, (SOCKADDR*)&service, &size); // Getting a new connection
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("10.0.0.1");
service.sin_port = htons(2583);
int addrSize = sizeof(service);
if (sendto(s, "123", 3, NULL, (struct sockaddr*)&service, addrSize) != 3)
printf("%d", WSAGetLastError()); // Print error if did not send successfully
"10.0.0.1" is the IP of the Client (I made sure it is)...
I didnt found a way to get the IP automaticly from the socket, so I'm just putting it right away for now...
Here is my client code :
SOCKET ConnectToServer()
{
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
return NULL;
}
//----------------------
// Create a SOCKET for connecting to server
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ConnectSocket == INVALID_SOCKET)
{
WSACleanup();
return NULL;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(Default_IP.c_str()); // IP
clientService.sin_port = htons(Default_Port); // Port
//----------------------
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService)); // Connecting
while (iResult == SOCKET_ERROR) // ERROR, could not connect. keep trying
{
iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService)); // Connecting
}
return ConnectSocket;
}
In this code, I'm connecting to the client.
and here is the rest of the client code :
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("10.0.0.1");
service.sin_port = htons(2583);
s = ConnectToServer();
sendto(s, "123", 3, NULL, (struct sockaddr*)&service, addrSize);
while(true)
{
result = recvfrom(s, (char*)waveIn, NUMPTS * sizeof(short int), NULL, (struct sockaddr *)&service, &addrSize);
if (result > 0)
{
std::cout << "New Data!" << std::endl;
}
else
printf("%d\n", WSAGetLastError());
}
the sendto function in the client does work, and the server recieves it, though when the server tries to send data back to the client, it recieves nothing, and it is stuck on the recvfrom function.
What am I doing wrong?
P.S - I'm running both client and server from the same computer, which means both has the same IP adress ("10.0.0.1"), but it allways worked for me when using sockets with TCP, so I've did it here too.
though, I did try use this code with 2 different computers, and I still had the same error...
Thanks!
When the server calls recvfrom(), it reports the IP:Port that the data came from. You need to send your reply back to that same IP:Port, eg:
sockaddr_in service;
int size = sizeof(service);
char data[500];
int len = recvfrom(s, data, 500, NULL, (SOCKADDR*)&service, &size);
if (len == -1)
printf("recv failed: %d", WSAGetLastError()); // Print error if did not recv successfully
else
{
if (sendto(s, "123", 3, NULL, (struct sockaddr*)&service, size) == -1)
printf("send failed: %d", WSAGetLastError()); // Print error if did not send successfully
}

can a windows service run a TCP server?

I created 2 programs in c++ using visual studio 2008: a windows service based on this service which i added tcp server code to and a client program using MFC, which has a listbox that displays the ip address and hostname of the computer thats running the service. The user then chooses a server and clicks a connect button. Since there will be many servers running, I used some PHP script on a web host site. The service sends its ip address and host name to the web host, the web host puts the information into a list and the client then accesses this list.
all this works fine with the server code but when i put the server code into the windows service, the client program freezes and doesn't respond when the connect button is clicked. The ip address and host name still appear in the client listbox, i just can't connect to the server i select.
is the windows service stopping the server code from working?
here is the cpp file that contains the server code in the service program:
char* WebPost(char Website[], char Webpage[], char Request[], int RetLen)
{
// Sends an HTTP Post request with POST Data...
SOCKET WebSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *WebHost;
WebHost = gethostbyname(Website);
if (WebHost == NULL)
{
if (WSAGetLastError() == WSANOTINITIALISED)
printf("Error Not Connected!");
else
printf("Error: %d", WSAGetLastError());
Sleep(1000);
exit(0);
}
SOCKADDR_IN SockAddr;
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)WebHost->h_addr);
connect(WebSocket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr));
char PostRequest[1024];
sprintf(PostRequest,
"POST %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Content-Length: %hu\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"\r\nD=%s\0",
Webpage, Website,
strlen(Request)+2, Request
);
send(WebSocket, PostRequest, strlen(PostRequest), 0);
// Get return data
char* Data = new char[RetLen];
recv(WebSocket, Data, 4, 0);
for (;;)
{ // Skip HTTP headers
Data[0] = Data[1];
Data[1] = Data[2];
Data[2] = Data[3];
recv(WebSocket, &Data[3], 1, 0);
if (Data[0] == '\r' && Data[1] == '\n'
&& Data[2] == '\r' && Data[3] == '\n')
break;
}
int DataLen = recv(WebSocket, Data, RetLen, 0);
Data[DataLen] = '\0'; // Return the data
shutdown(WebSocket, 2);
closesocket(WebSocket);
return Data;
}
void ServStart()
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{
printf("WSAStartup failed with error %ld.\n", WSAGetLastError());
exit(0);
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("The dll do not support the Winsock version %u.%u!\n", LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion));
WSACleanup();
exit(0);
}
//Start listening
ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListeningSocket == INVALID_SOCKET)
{
printf("Error at socket, error code: %ld.\n", WSAGetLastError());
WSACleanup();
exit(0);
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(Port);
ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)
{
printf("bind failed. Error code: %ld.\n", WSAGetLastError());
closesocket(ListeningSocket);
WSACleanup();
exit(0);
}
if (listen(ListeningSocket, 5) == SOCKET_ERROR)
{
printf("listen: Error listening on socket %ld.\n", WSAGetLastError());
closesocket(ListeningSocket);
WSACleanup();
exit(0);
}
char ac[80];
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR)
{
printf("Error when getting local host name: ", WSAGetLastError());
exit(0);
}
struct hostent *phe = gethostbyname(ac);
if (phe == 0)
{
printf("Error: ", WSAGetLastError());
exit(0);
}
struct in_addr addr;
memcpy(&addr, phe->h_addr_list[0], sizeof(struct in_addr)); // use the first ip-address
printf("IP used by Server: %s\n", inet_ntoa(addr)); // inet_ntoa(addr) provides the local address.
MyIP = inet_ntoa(addr);
char SendBuf[32];
// * is used as a separator, because it's not allowed in the hostname.
//So it won't interfere with it.
sprintf(SendBuf, "%hhu|%s*%s", cAddIP, MyIP, ac); // Send the server the IP and host name
WebPost(WEBSITE, WEBPAGE, SendBuf, 0);
printf("listening for connections...\n\n");
}
void ShutDown() // Shut down the server (tells the web server I am offline)
{
char SendBuf[32]; // Remove my IP from the list of online servers...
char ac[80];
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR)
{
printf("Error when getting local host name: ", WSAGetLastError());
exit(0);
}
sprintf(SendBuf, "%hhu|%s*%s", cRemIP, MyIP,ac);
WebPost(WEBSITE, WEBPAGE, SendBuf, 0);
printf("Successful shutdown\n");
Sleep(1000);
WSACleanup();
}
void ServLoop()
{
SOCKADDR_IN SenderInfo;
SOCKET NewConnection;
int ByteReceived, nlen;
char recvbuff[1024];
for (;;)
{
//Main program loop
NewConnection = SOCKET_ERROR;
while(NewConnection == SOCKET_ERROR)
{
NewConnection = accept(ListeningSocket, NULL, NULL); // this is a blocking function
printf("New client got connected, ready to receive and send data...\n\n");
ByteReceived = recv(NewConnection, recvbuff, sizeof(recvbuff), 0);
if (ByteReceived > 0)
{
getsockname(ListeningSocket, (SOCKADDR *)&ServerAddr, (int *)sizeof(ServerAddr));
memset(&SenderInfo, 0, sizeof(SenderInfo));
nlen = sizeof(SenderInfo);
getpeername(NewConnection, (SOCKADDR *)&SenderInfo, &nlen);
}
}
if (shutdown(NewConnection, 2) != 0)
printf("there is something wrong with the shutdown. The error code: %ld\n", WSAGetLastError());
else
printf("shutdown is working...\n");
}
}
// --------------------------------------------
BOOL ConsoleProc(DWORD Msg)
{
switch (Msg)
{
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
ShutDown();
return false;
}
return false;
}
// -----------------------------------------------------
CSampleService::CSampleService(PWSTR pszServiceName,
BOOL fCanStop,
BOOL fCanShutdown,
BOOL fCanPauseContinue) :
CServiceBase(pszServiceName, fCanStop, fCanShutdown, fCanPauseContinue),
m_dwTimeout(10 * 1000)
{
// Create a manual-reset event that is not signaled at first to indicate
// the service is stopping.
m_hStoppingEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hStoppedEvent == NULL)
{
throw GetLastError();
}
// Create a manual-reset event that is not signaled at first to indicate
// the stopped signal of the service.
m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hStoppedEvent == NULL)
{
throw GetLastError();
}
}
CSampleService::~CSampleService(void)
{
if (m_hStoppedEvent)
{
CloseHandle(m_hStoppedEvent);
m_hStoppedEvent = NULL;
}
if (m_hStoppingEvent)
{
CloseHandle(m_hStoppingEvent);
m_hStoppingEvent = NULL;
}
}
void CSampleService::OnStart(DWORD dwArgc, LPWSTR *lpszArgv)
{
WriteErrorLogEntry(L"CSampleService::Start: function entry");
// Log a service start message to the Application log.
WriteEventLogEntry(L"CppWindowsService in OnStart", EVENTLOG_INFORMATION_TYPE);
// Queue the main service function for execution in a worker thread.
CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this);
WriteErrorLogEntry(L"CSampleService::Start: function exit");
}
void CSampleService::ServiceWorkerThread(void)
{
WriteErrorLogEntry(L"CSampleService::ServiceWorkerThread: running");
// Periodically check if the service is stopping.
while (WaitForSingleObject(m_hStoppingEvent, m_dwTimeout) == WAIT_TIMEOUT)
{
// Perform main service function here...
// Handle console events
SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleProc, TRUE);
ServStart(); // Main loop is in another thread
ServLoop(); // The never returning server loop
}
// Signal the stopped event.
SetEvent(m_hStoppedEvent);
WriteErrorLogEntry(L"CSampleService::ServiceWorkerThread: done");
}
void CSampleService::OnStop()
{
ShutDown(); //shut down server
SetServiceStatus(SERVICE_STOP_PENDING, ERROR_SUCCESS, 30 * 1000);
WriteErrorLogEntry(L"CSampleService::Stop: function entry");
// Log a service stop message to the Application log.
WriteEventLogEntry(L"CppWindowsService in OnStop", EVENTLOG_INFORMATION_TYPE);
// Indicate that the service is stopping and wait for the finish of the
// main service function (ServiceWorkerThread).
SetEvent(m_hStoppingEvent);
if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
{
SetServiceStatus(SERVICE_STOP_PENDING, ERROR_INVALID_DATA, 30 * 1000);
WriteErrorLogEntry(L"OnStop: Service Start", GetLastError());
throw GetLastError();
}
WriteErrorLogEntry(L"CSampleService::Stop: function exit");
}
The answer to your specific question is, yes, a windows service can run a TCP server.
The answer to why yours does not work is not clear. At first glance the service code looks reasonable. It's possible connections to your service are being blocked by your OS firewall (i.e. your console one is in the accept list but your service one is not). You might convert some of your error printf logic into something that prints to a file instead (e.g. fprintf?) so you can take a look at what's going on...
Sure, of course it can. Why would it not be possible?