I am working on a simple client-server application. However, after client runs, i get the message error 10038 with the recv(), in the server side. The socket number descriptor retains the same value in both client and server, thus i think there is no a socket error. Any help would be appreciated.
client:
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
// Need to link with Ws2_32.lib.
#pragma comment(lib, "ws2_32.lib")
int wmain()
{
// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
printf("WSAStartup() failed with error: %d\n", iResult);
return 1;
}
// Create a socket for connecting to server.
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket() failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
printf("Socket descriptor: %d\n",ConnectSocket);
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in Service;
memset(&Service, 0, sizeof(Service));
Service.sin_family = AF_INET;
Service.sin_addr.s_addr = inet_addr("127.0.0.1");
Service.sin_port = htons(27015);
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR *) &Service, sizeof (Service));
if (iResult == SOCKET_ERROR) {
printf("connect() failed with error: %ld\n", WSAGetLastError());
iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR)
printf("closesocket() failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
printf("Connected to server.\n");
// Message that has to be sent.
char receiveBuffer[1000];
char message[1000];
printf("\nEnter message: ");
gets_s(message);
printf("Message you wrote is: %s\n", message);
// Send a message.
if (send(ConnectSocket, message, sizeof(message), 0) == SOCKET_ERROR)
{
printf("send() failed with error code: %d\n", WSAGetLastError());
}
printf("Message successfully sent to server.");
// Receive a message.
if (recv(ConnectSocket, receiveBuffer, 1000, 0) == SOCKET_ERROR)
{
printf("recv() failed with error code: %d\n", WSAGetLastError());
while(1);
}
printf("\nServer says:");
printf(receiveBuffer,sizeof(receiveBuffer));
while(1);
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
server:
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
int wmain()
{
// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
printf("WSAStartup() failed with error: %d\n", iResult);
return 1;
}
// Create a socket for connecting to client.
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket() failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
printf("Socket descriptor: %d\n", ConnectSocket);
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in Service;
memset(&Service, 0, sizeof(Service));
Service.sin_family = AF_INET;
Service.sin_addr.s_addr = inet_addr("127.0.0.1");
Service.sin_port = htons(27015);
//Bind.
if (bind(ConnectSocket, (struct sockaddr *)&Service, sizeof(Service)) == SOCKET_ERROR)
{
printf("Bind failed with error code: %d\n" , WSAGetLastError());
}
printf("Bind done.\n");
// Listen on the socket for a client.
if (listen(ConnectSocket, 1) == SOCKET_ERROR)
{
printf ("listen() failed with error: %ld\n", WSAGetLastError() );
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("listen() run successfully.\n");
// Accept a connection from a client.
SOCKET acceptSocket;
acceptSocket = accept(ConnectSocket, NULL, NULL);
if (acceptSocket == INVALID_SOCKET) {
printf("accept() failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
else{
printf("accept() run successfully.\n");
}
// No longer need server socket.
closesocket(ConnectSocket);
char receiveBuffer[1000];
int recv_len;
printf("\nWaiting for data...\n");
fflush(stdout);
// Receive a message.
if (recv_len = recv(ConnectSocket, receiveBuffer, 1000, 0) == SOCKET_ERROR)
{
printf("Socket descriptor, after recv(): %d\n", ConnectSocket);
printf("recv() failed with error code: %d\n", WSAGetLastError());
while(1);
}
// Send a message.
if (send(ConnectSocket, receiveBuffer, recv_len, 0) == SOCKET_ERROR)
{
printf("sendto() failed with error code: %d\n", WSAGetLastError());
while(1);
}
else
printf("\nMessage sent back to client.");
while(1);
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
I am a beginner at Winsock programming and any help would be appreciated.
Error 10038 is WSAENOTSOCK, which means you do not have a valid socket. On the server side, you are using the server socket (ConnectSocket) after you have closed it. To receive and send, you need to use the connected socket (acceptSocket) instead. Also, you need to close acceptSocket when you are done with it, do not close ConnectSocket a second time.
Related
So I wanted to learn more on how the TCP protocol works and started messing with windows sockets (WinSocks2), I managed to write a basic server and client from the Microsoft documentation.
I expected to see a 3-way handshake in Wireshark, and I did but not in the way I imagined, it was actually duplicated (The server sends the same packets as the client back to the client).
So my question is, is this normal, or am I doing something wrong?
Here is my source code of the server:
// This should be placed before #include <Windows.h> if the windows include is used
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <cstdio>
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
/// TEST CODE /// REMOVE AFTER TESTING WAS DONE ///
int main()
{
WSADATA wsaData;
int iResult;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
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;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo("0.0.0.0", "1337", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET)
{
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
}
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR)
{
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Handling pending connections
puts("Waiting for a connection..");
SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
int size =0 ;
// Receive until the peer shuts down the connection
do
{
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
{
printf("Bytes received: %d\n", iResult);
size += iResult;
// I thought this was the problem but after I removed it from the code it still was the same.
//
// Echo the buffer back to the sender
//iSendResult = send(ClientSocket, recvbuf, iResult, 0);
/*if (iSendResult == SOCKET_ERROR)
{
printf("send failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}*/
//printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else
{
printf("recv failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
}
while (iResult > 0);
recvbuf[size] = 0;
printf("Data received: %s\n", recvbuf);
// Stops responding to requests, still can accept tho
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// Close socket, no receiving/sending
closesocket(ClientSocket);
WSACleanup();
}
And here is the client:
// This should be placed before #include <Windows.h> if the windows include is used
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <cstdio>
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
/// TEST CODE /// REMOVE AFTER TESTING WAS DONE ///
int main()
{
WSADATA wsaData;
int iResult;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
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;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo("109.xxx.xxx.xxx", "1337", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
}
iResult = connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == 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)
{
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
#define DEFAULT_BUFLEN 512
int recvbuflen = DEFAULT_BUFLEN;
const char* sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR)
{
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// 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, recvbuflen, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
}
while (iResult > 0);
closesocket(ConnectSocket);
WSACleanup();
}
Here is the packets captured from Wireshark, where the IP address starting with 109.xxx.xxx.xxx is the server:
No, the duplicate packets are not normal. But that is not related to your code. It is more likely an issue with your network setup, or just a side effect of how you are capturing the packets.
Unrelated to the duplicate packets, there are other problems with the code shown.
In your server:
your if (ListenSocket == INVALID_SOCKET) block is missing a return, so if socket() fails then you still call bind() with an invalid SOCKET and are dereferencing an invalid result pointer.
Once you reach your recv() loop, you are never closing the ListenSocket before calling WSACleanup().
your printf() of recvbuf needs to be inside the loop when iResult > 0. And if you are going to null-terminate recvbuf then you need to use recvbuflen-1 when calling recv(), or else you will lose the last byte received. Otherwise, pass iResult as a parameter to printf() so you don't need to null-terminate recvbuf at all.
In your client:
do not use the AI_PASSIVE flag when calling getaddrinfo(). That flag is meant for listening servers, not outbound clients.
your if (ConnectSocket == INVALID_SOCKET) block is missing a return, so if socket() fails then you still call connect() with an invalid SOCKET and are dereferencing an invalid result pointer.
Try this code instead:
server:
// This should be placed before #include <Windows.h> if the windows include is used
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <cstdio>
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
/// TEST CODE /// REMOVE AFTER TESTING WAS DONE ///
int main()
{
WSADATA wsaData;
int iResult;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
struct addrinfo* result = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo(NULL, "1337", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET)
{
printf("Error at socket(): %d\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR)
{
printf("Listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Handling pending connections
puts("Waiting for a connection..");
SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int iSendResult;
// Receive until the peer shuts down the connection
do
{
iResult = recv(ClientSocket, recvbuf, sizeof(recvbuf), 0);
if (iResult > 0)
{
printf("Bytes received: %d\n", iResult);
printf("Data received: %.*s\n", iResult, recvbuf);
// Echo the buffer back to the sender
/*iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (iSendResult == SOCKET_ERROR)
{
printf("send failed: %d\n", WSAGetLastError());
break;
}
printf("Bytes sent: %d\n", iSendResult);*/
}
else if (iResult == 0)
{
printf("Connection closing...\n");
}
else
{
printf("recv failed: %d\n", WSAGetLastError());
}
}
while (iResult > 0);
// Close socket, no receiving/sending
shutdown(ClientSocket, SD_BOTH);
closesocket(ClientSocket);
WSACleanup();
return 0;
}
client:
// This should be placed before #include <Windows.h> if the windows include is used
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <cstdio>
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
/// TEST CODE /// REMOVE AFTER TESTING WAS DONE ///
int main()
{
WSADATA wsaData;
int iResult;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
struct addrinfo* result = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo("109.xxx.xxx.xxx", "1337", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ConnectSocket = INVALID_SOCKET;
for(struct addrinfo* ptr = result; ptr != NULL; ptr = ptr->ai_next)
{
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Error at socket(): %d\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen);
freeaddrinfo(result);
if (iResult != SOCKET_ERROR)
break;
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
if (ConnectSocket == INVALID_SOCKET)
{
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
#define DEFAULT_BUFLEN 512
const char* sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR)
{
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// 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)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
}
while (iResult > 0);
shutdown(ConnectSocket, SD_RECEIVE);
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
INTRODUCTION:
I have studied the MSDN examples for blocking TCP server and blocking TCP client.
I wanted to try something simple, in view of modifying those examples to create simple chat application.
I have tried to implement the following, for a start:
send message from server
receive and display that message on client
send response from client
receive and display the response from client
RELEVANT INFORMATION
I apologize in advance for the lengthy code, but i strongly believe it is relevant for me to submit SSCCE for both client and the server, in order for community to stand a chance for solving the problem.
I have tried to keep the code as minimal as possible, but did not want to omit basic error checking.
You can copy/paste both in single .cpp file, and they should compile and run without problem:
Server code:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int __cdecl main(void)
{
WSADATA wsaData;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iResult;
char recvbuf[DEFAULT_BUFLEN] = "";
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// No longer need server socket,
// because I want to accept only 1 client
closesocket(ListenSocket);
// ===================== let us try to send a message...
std::string message = "Test message from server !!!";
int total = message.size();
const int messageLength = message.size();
while (iResult = send( ClientSocket,
// send only the missing part of the string, if send failed to deliver entire packet:
// we move the start of the string forward by messageLength - total
// while we send remaining number of bytes, which is held in total
message.substr(messageLength - total, total).c_str(), total, 0),
iResult > 0)
{
total -= iResult;
}
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
/* // adding this, seems to solve the problem ???
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
*/
// receive response from client...
while (iResult = recv(ClientSocket, recvbuf, recvbuflen, 0), iResult > 0)
{
printf("%s", recvbuf);
memset(recvbuf, '\0', sizeof(recvbuf));
}
if(iResult < 0)
{
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
getchar(); // so I can stop the console from immediately closing...
return 0;
}
Client code:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char recvbuf[DEFAULT_BUFLEN] = "";
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &result);
if ( iResult != 0 )
{
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next)
{
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// receive message from server...
while (iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0), iResult > 0)
{
printf("%s", recvbuf);
memset(recvbuf, '\0', sizeof(recvbuf));
}
if(iResult < 0)
{
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// ===================== let us try to send a message...
std::string message = "Client response...";
int total = message.size();
const int messageLength = message.size();
while (iResult = send( ConnectSocket,
// send only the missing part of the string, if send failed to deliver entire packet:
// we move the start of the string forward by messageLength - total
// while we send remaining number of bytes, which is held in total
message.substr(messageLength - total, total).c_str(), total, 0),
iResult > 0)
{
total -= iResult;
}
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ConnectSocket);
WSACleanup();
getchar(); // so I can stop the console from immediately closing...
return 0;
}
PROBLEM:
I have implemented the solution, but did not get the expected result.
Server sends the message, client successfully receives and displays it, but then client gets stuck infinitely, instead of sending it's response to the server, which blocks the server infinitely as well.
MY EFFORTS TO SOLVE THIS:
First try:
Using the Debugger, I have placed breakpoint after client's receive block only to determine client never gets there after it receives first message.
I believe while loop should call recv again, which should return 0, thus forcing the loop to end.
Debugger doesn't even continue to show the content of client's receive buffer after I hit Continue, instead it exhibits behavior I can not describe at this moment since I am not a native English speaker.
Second try:
I have also tried to put receiving loop from server into thread, using CreateThread, but that did not help either.
I have also tried to put receiving loop from the client into thread, but that failed too.
I have tried to put both client and server receiving loops into thread, but that failed too.
Third try:
Finally, I have added the call to shutdown( ClientSocket, SD_SEND) in the server code, you shall find it at the lower part of the code, it is commented out.
This seems to fix the problem, but i am not sure if this is the right solution since i am just starting with Winsock.
QUESTIONS:
How can I bypass my "solution" of adding shutdown after send ?
If the above is the only way, should I do the same after recv and what argument should I send (SD_SEND, SD_RECEIVE or SD_BOTH) ?
Again, I apologize for lengthy post, but being new to this I have tried to provide as much info as possible in order to make your task easier.
After a brief glance at your code I would venture to guess that the following code block in the client:
while (iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0), iResult > 0)
{
printf("%s", recvbuf);
memset(recvbuf, '\0', sizeof(recvbuf));
}
is actually your issue. You mentioned that shutting down the socket on the serverside fixes the problem. With sockets, the recv call is going to block as long as the socket is alive or until data comes through, but when the socket is closed you will get a recv of 0.
Instead of looping on recv, if you want to just receive one message you should either loop back to the recv call after processing the first recv or you should poll on the socket to see if there is actually data available first.
I'm trying to check whether port on my pc is available or not. But this code crashes after the acceptor.listen();. Crash stack trace stops at:
detail/impl/win_iocp_socket_service_base.ipp
My code is:
try {
boost::asio::io_service io_service;
boost::asio::ip::tcp::acceptor acceptor(io_service);
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string("127.0.0.1"), port);
acceptor.open(endpoint.protocol());
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(false));
acceptor.bind(endpoint);
acceptor.listen();
}
catch (...) {
// port busy
}
How can I check this with boost or where is the problem in my code?
UPD1: I tried following code from here:
bool port_in_use(unsigned short port) {
using namespace boost::asio;
using ip::tcp;
io_service svc;
tcp::acceptor a(svc);
boost::system::error_code ec;
a.open(tcp::v4(), ec) || a.bind({ tcp::v4(), port }, ec);
return ec == error::address_in_use;
}
but after function executes, my program crashes still in same place.
Well, I found how to do this in windows (from link):
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
int wmain()
{
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup function failed with error: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// 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("127.0.0.1");
clientService.sin_port = htons(27015);
//----------------------
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService));
if (iResult == SOCKET_ERROR) {
wprintf(L"connect function failed with error: %ld\n", WSAGetLastError());
iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR)
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
wprintf(L"Connected to server.\n");
iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
WSACleanup();
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to get multi threading working on my simple server project. It was working fine on my laptop, yet when I moved the project folder to my desktop, it gives me an unhandled exception at my std::thread call.
I have a method StartAcceptingClients() which works fine when unthreaded and called on it's own. However when I call it by new thread:
std::thread clientsThread(StartAcceptingClients);
It throws:
Unhandled exception at 0x62E50BD0 in WinsockServer.exe: 0xC0000005: Access violation reading location 0x62E50BD0.
MCVE:
#pragma once
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <thread>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
#include "Client.h"
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
const int MAXUSERS = 8;
Client* clients[MAXUSERS];
void ListenForNewClient()
{
//Listen to socket
printf("Listening for connections...\n");
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
std::cin.get();
return;// 1;
}
}
Client* AcceptNewClient()
{
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
std::cin.get();
return NULL;// 1;
}
Client* client = new Client(); client->socket = ClientSocket;
for (int i = 0; i < MAXUSERS; i++)
{
if (clients[i] == NULL)
{
clients[i] = client;
clients[i]->clientID = i;
printf("Client %i has joined.\n", i);
break;
}
}
// No longer need server socket
closesocket(ListenSocket);
return client;
}
void StartRecievingFromClient(Client* client)
{
// Receive until the peer shuts down the connection
do {
iResult = recv(client->socket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
// Echo the buffer back to the sender
iSendResult = send(client->socket, recvbuf, iResult, 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(client->socket);
WSACleanup();
std::cin.get();
return;// 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Client %i has disconnected.\n", client->clientID);
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(client->socket);
WSACleanup();
std::cin.get();
return;// 1;
}
} while (iResult > 0);
}
void StartAcceptingClients()
{
ListenForNewClient();
Client* client = AcceptNewClient();
client->listenThread = new std::thread(StartRecievingFromClient, client);
}
//int __cdecl main(void)
int main()
{
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
std::cin.get();
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
std::cin.get();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
std::cin.get();
return 1;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
std::cin.get();
return 1;
}
freeaddrinfo(result);
std::thread clientsThread(StartAcceptingClients);
printf("Game Loop Started.\n");
//Game Loop
while (true)
{
std::string Command;
std::getline(std::cin, Command);
}
printf("Game Loop Ended.\n");
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
std::cin.get();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
std::cin.get();
return 0;
}
I am very new to c++. Recently I am trying to pass some data to a php file in c++ via the post method. I have tried a tutorial from MSDN send Function. The code is as follows:
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <conio.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 27015
int main() {
//----------------------
// Declare and initialize variables.
int iResult;
WSADATA wsaData;
struct hostent *host;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
int recvbuflen = DEFAULT_BUFLEN;
char *sendbuf = "Client: sending data test";
char recvbuf[DEFAULT_BUFLEN] = "";
//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
clientService.sin_port = htons( 80 );
//----------------------
// Connect to server.
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
if (iResult == SOCKET_ERROR) {
wprintf(L"connect failed with error: %d\n", WSAGetLastError() );
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
//----------------------
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
wprintf(L"send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %d\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
wprintf(L"shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
wprintf(L"Bytes received: %d\n", iResult);
else if ( iResult == 0 )
wprintf(L"Connection closed\n");
else
wprintf(L"recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
// close the socket
iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"close failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
WSACleanup();
getch();
}
It sends data to the homepage of localhost but I would like to send data somewhere else in localhost(eg. like 'localhost/test/index.php'). If I change the code from clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" ); to clientService.sin_addr.s_addr = inet_addr( "127.0.0.1/test/index.php" ); then I receive some errors in the exe file. But the program compiles successfully.
Please give me a solution. What should I do now?
You are taking the wrong approach. The low-level socket layer only allows you to connect to a specific server (for example your local http server running on 127.0.0.1 listening on port 80) and send raw data. You need to talk HTTP with that server to really do what you want to do.
I suggest that if you are new to C++, you look at one of the many third-party libraries for C++ which allow you to "talk HTTP" with a http server - for example, libCurl