I am making a Winsock application, and something fails in the server when it tries to make the shutdown funtion. The project builds and runs, but when the first connection of the client arrives it takes it and fails showing in the comand line:
"shutdown failed with error: 10038".
I have been reading about the error and it is said that it is usually because the funcion shutdown is applied to something that is not a SOCKET, or like that. But when debugging I saw that apparently it is a Socket, so I don't know what to do.
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include "stdafx.h"
// 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"
//Function declaration
const std::string currentDateTime();
int __cdecl NewClient(SOCKET ListenSocket, SOCKET ClientSocket, char *recvbuf, int recvbuflen, int iSendResult, int iResult);
std::string CommandGet(char *recvbuf);
void Login(char *recvbuf);
void print_data(char *recvbuf);
string GetUsername(char *recvbuf);
string GetThirdToken(char *recvbuf);
//Map & Struct creation
struct message{
static unsigned int last_id;
unsigned int id;
std::string baa;
std::string timestamp;
message(){};
message(const std::string& recvbuf_baa,const std::string& a_timestamp) :
baa(recvbuf_baa), timestamp(a_timestamp), id(++last_id)
{
}
};
map<std::string,std::vector<message *> > data;
map<std::string,std::vector<string> > followers;
//Global variables
unsigned int message::last_id = 0;
map<std::string,bool> loggedin;
int __cdecl main(void)
{
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult=0;
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;
while(true){
// 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
closesocket(ListenSocket);
return NewClient(ListenSocket, ClientSocket, recvbuf, recvbuflen, iSendResult, iResult);
}
}
int __cdecl NewClient(SOCKET ListenSocket, SOCKET ClientSocket, char *recvbuf, int recvbuflen, int iSendResult, int iResult){
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
std::string cmd=CommandGet(recvbuf);
if (cmd=="log"){
std::string usrn=GetUsername(recvbuf);
std::string recvbuf_str="";
for(auto it=loggedin.begin();it!=loggedin.end();it++){
if ((*it).first==usrn){
recvbuf_str="loggedin";
if ((*it).second){
recvbuf_str="cantlogin";
break;
}
else{
loggedin[usrn]=1;
break;
}
break;
}
}
if (recvbuf_str==""){
recvbuf_str="newlogin";
Login(recvbuf);
}
iSendResult = send( ClientSocket, recvbuf_str.c_str(), iResult, 0 );
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
}
}
else if (iResult == 0){
printf("Connection closing...\n");
closesocket(ClientSocket);}
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
// 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();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
const std::string currentDateTime() {
time_t now = time(0);
struct tm tstruct;
char buf[80];
localtime_s(&tstruct, &now);
strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);
return buf;
}
void Login(char *recvbuf){
std::string usrn= GetUsername(recvbuf);
std::vector<message *> messages;
data[usrn]=messages;
std::vector<string> follow;
followers[usrn]=follow;
loggedin[usrn]=1;
}
void print_data(char *recvbuf){
std::string usrn= GetUsername(recvbuf);
for(auto mapIt = data.cbegin(); mapIt != data.cend(); ++mapIt)
{
std::cout << "printing data for " << mapIt->first << ":" << std::endl;
for(auto vectIter = mapIt->second.cbegin(); vectIter != mapIt->second.cend(); ++vectIter)
{
std::cout << (*vectIter)->baa << ", " << (*vectIter)->timestamp << ", "
<< (*vectIter)->id << std::endl;
}
}
}
void print_followers(char *recvbuf){
std::string usrn= GetUsername(recvbuf);
for(auto mapIt = followers.cbegin(); mapIt != followers.cend(); ++mapIt)
{
std::cout << "printing followers for " << mapIt->first << ":" << std::endl;
for(auto vectIter = mapIt->second.cbegin(); vectIter != mapIt->second.cend(); ++vectIter)
{
std::cout << (*vectIter) << endl;
}
}
}
std::string CommandGet(char *recvbuf){
int start0=0;
std::string recvbuf_cmd;
std::string recvstr(recvbuf);
start0=recvstr.find(';');
recvbuf_cmd=recvstr.substr(0,start0);
return recvbuf_cmd;
}
string GetUsername(char *recvbuf){
int start0=0, start1=0;
std::string recvbuf_usrn;
std::string recvstr(recvbuf);
start0=recvstr.find(';');
start1=recvstr.find(';',start0+1);
recvbuf_usrn=recvstr.substr(start0+1,start1-start0-1);
return recvbuf_usrn;
}
string GetThirdToken(char *recvbuf){
int start0=0, start1=0, start2=0;
std::string recvbuf_thirdtoken;
std::string recvstr(recvbuf);
start0=recvstr.find(';');
start1=recvstr.find(';',start0+1);
start2=recvstr.find(';',start1+1);
recvbuf_thirdtoken=recvstr.substr(start1+1,start2-start1-1);
return recvbuf_thirdtoken;
}
I upload the whole project in case you want to check it deeper( https://mega.nz/#!dtcx1DCL!dKWV2ryDDfiXv5H3Mi2p4PrBpie2CGrGJOTAwvQAV8M), but the problem is located in the server(which i simplified the code), the client is just so you can start the conection entering the username(but dont care about it).
Thank you in advance, any help will be appreciated.
Lets consider the following lines, take from your shown source:
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
...
else if (iResult == 0){
printf("Connection closing...\n");
closesocket(ClientSocket);}
...
iResult = shutdown(ClientSocket, SD_SEND);
When recv returns zero that means the connection has been closed (nicely) by the other end. When that happens you call closesocket to close the socket. But then you proceed to unconditionally call shutdown on the closed socket, leading to the error you got.
Simple solution? Just close the socket using closesocket once, no need for shutdown here that I can see (there seldom are).
Related
I have made Mutlti-Client sever that can receive and send messages to the sever and the sever can send back the messages to clients but the problem I'm having is client A will not be able to receive the message from client B unless Client A sends a message I want the clients to receive messages anytime I also want to be to type commands on the sever without stopping the flow of sending to clients and receiving message from clients
I have tried moving the std::getline(std::cin, ClientInput); to different place in the code so clients could be able to see message but I have notice in the code the while loop does not continue because of it is there a way to get user input with out stopping the loop so can send and receive messages
This the Client code
int Client::OnCreate()
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL, *ptr = NULL, hints;
char sendbuf[] = "this is a test";
std::vector<SOCKET> ConnectedUser;
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);
system("pause");
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("localhost", DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
system("pause");
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();
system("pause");
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();
system("pause");
return 1;
}
// Send an initial buffer
std::string ClientInput;
std::cout << "please send a message " << std::endl;
std::getline(std::cin, ClientInput);
do {
if (ClientInput.size() > 0)
{
//send user input to sever
iResult = send(ConnectSocket, ClientInput.c_str(), ClientInput.size(), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
system("pause");
return 1;
}
printf("Bytes Sent: %d\n", iResult);
if (iResult != SOCKET_ERROR)
{
//receive user input from sever
int iUserResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iUserResult > 0)
{
std::cout << "Client receive this message from sever \t" << std::string(recvbuf, 0, iResult) << std::endl;
printf("Bytes received: %d\n", iUserResult);
}
}
//will disconnect from the sever
if (iResult == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
system("pause");
}
//will disconnect from the sever if user types in logoff
if (ClientInput == "logoff")
{
closesocket(ConnectSocket);
WSACleanup();
printf("Connection closing goodbye sever\n");
system("pause");
}
//close connection if the no user input
if (iResult == 0) {
printf("Connection closed\n");
iResult = shutdown(ConnectSocket, SD_SEND);
}
}
std::getline(std::cin, ClientInput);
} while (ClientInput.size() > 0);
// cleanup
closesocket(ConnectSocket);
system("pause");
WSACleanup();
return 0;
}```
This is the sever code
std::vector<SOCKET> ConnectedUser;
std::vector<int> UserInt;
unsigned __stdcall ClientSession(void *data)
{
char recvbuf[DEFAULT_BUFLEN];
int recvbufleng = DEFAULT_BUFLEN;
int iResult;
int iSendResult;
SOCKET ClientSocket = (SOCKET)data;
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;
do
{
iResult = recv(ClientSocket, recvbuf, recvbufleng, 0);
///iResult = recv(ClientSocket, recvbuf, sizeof(Player), 0);
std::cout << iResult << std::endl;
if (iResult > 0) {
for (int i = 0; i < ConnectedUser.size(); i++) {
std::cout << "send message to "<< ConnectedUser[i] << std::endl;
//iSendResult = send(ClientSocket, recvbuf, iResult, 0);
iSendResult = send(ConnectedUser[i], recvbuf, iResult, 0);
//ConnectedUser.clear();
//iSendResult = sendto(ConnectedUser[i], recvbuf, iResult, 0, (sockaddr*)&hints, sizeof(hints));
}
std::cout << "ClientSocket" << ClientSocket << std::endl;
if (iSendResult == SOCKET_ERROR)
{
printf("send failed with error: %d \n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Received Message %.*s\n", iResult, recvbuf);
}
else if (iResult == 0)
{
printf("connection closing.... \n");
std::cout << "user logged off" << ClientSocket << std::endl;
}
else
{
printf("recv failed with error: %d \n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d \n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
closesocket(ClientSocket);
}
int Sever::OnCreate()
{
WSADATA wsaData;
int iResult;
SOCKET ClientSocket = INVALID_SOCKET;
//send to
char recvbuf[DEFAULT_BUFLEN];
int recvbufleng = DEFAULT_BUFLEN;
int iSendResult;
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;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
//create the winsocket
if (iResult != 0) {
printf("WSAStartup failed: %d\n, iResult");
return 1;
}
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ListenSocket = INVALID_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;
}
// Create the master file descriptor set and zero it
fd_set master;
FD_ZERO(&master);
FD_SET(ListenSocket, &master);
fd_set copy = master;
int socketCount = select(0, ©, nullptr, nullptr, nullptr);
std::cout << " socketCount "<< socketCount << std::endl;
//// Send an initial buffer
//if (socketCount == 0) {
// std::string SeverInput;
// std::cout << "input Server command" << std::endl;
// std::getline(std::cin, SeverInput);
//
// if (SeverInput == "exit")
// {
// closesocket(ClientSocket);
// WSACleanup();
// printf("Connection closing goodbye sever\n");
// }
//}
for (int i = 0; i < socketCount; i++)
{
SOCKET sock = copy.fd_array[i];
if (sock == ListenSocket)
{
//// Accept a new connection
while ((ClientSocket = accept(ListenSocket, NULL, NULL))) {
if (ClientSocket == INVALID_SOCKET) {
printf("Accept failed with error: %d \n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
/* Messtotal.push_back(ClientSocket + "\n");*/
// Add the new connection to the list of connected clients
FD_SET(ClientSocket, &master);
ConnectedUser.push_back(ClientSocket);
std::cout << "client:" << ClientSocket <<" has arrived on sever" <<std::endl;
// Create a new thread for the accepted client (also pass the accepted client socket).
unsigned threadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ClientSession, (void*)ClientSocket, 0, &threadID);
}
}
}
WSACleanup();
printf("Server shutting down ");
return 0;
```}
Moving the std::getline(std::cin, ClientInput) anywhere within loop in client code will not help you becase getline() is a blocking call. In this case you should use threads in client code.
You need to create a new thread in client code with while loop. In this thread you will incoming messages from another client.
Main thread in client code will handle user input from getline() and sending messages via send function within while loop.
For example in your client code you can create thread like this :
m_hTrhead = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)processMessage, (LPVOID)ConnectSocket, CREATE_SUSPENDED, 0);
if (m_hTrhead == NULL)
{
printf("Failed to create thread for receiving messages , error code : %ld \n", GetLastError());
return false;
}
And thread will will process messages in function processMessage like this :
DWORD WINAPI Socket::processMessage(LPVOID lpParam)
{
SOCKET ConnectSocket= reinterpret_cast <SOCKET>(lpParam);
while (WSAGetLastError() != WSAECONNRESET)
{
int iUserResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iUserResult > 0)
{
std::cout << "Client receive this message from sever \t" << std::string(recvbuf, 0, iResult) << std::endl;
printf("Bytes received: %d\n", iUserResult);
}
}
}
Be aware that non- blocking sockets exists also (So thread will not stop at recv or send function). Function names for non-blocking socket are the same but you must set the socket itself to non-blocking.
u_long mode = 1; // enable non-blocking socket
ioctlsocket(sock, FIONBIO, &mode);
You can read about this more here
My code between the client and server works as expected except for the connection closing prematurely after only one message has been sent or received. I want both the client and the server to stay open to send multiple messages without having to reinitialize the connection every time. My code is below:
Server
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27016"
int __cdecl main(void)
{
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;
// 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(0, 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);
std::cout << "Server Starting..." << std::endl;
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);
std::cout << "Waiting for clients..." << std::endl;
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;
}
std::cout << "In the server loop ready to receive a command..." << std::endl;
// No longer need server socket
//closesocket(ListenSocket);
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
std::cout << recvbuf << std::endl;
// Echo the buffer back to the sender
iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (strcmp(recvbuf, "move") == 0) {
std::cout << "Command received: " << recvbuf << std::endl;
}
else if (strcmp(recvbuf, "stats") == 0) {
std::cout << "Command received: " << recvbuf << std::endl;
}
else if (strcmp(recvbuf, "shoot") == 0) {
std::cout << "Command received: " << recvbuf << std::endl;
}
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
// 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();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
system("PAUSE");
return 0;
}
Client
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <iostream>
using std::string;
using std::cin;
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27016"
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
// char *sendbuf = "this is a test"; // disallowed with /permissive- flag
//char *sendbuf = new char[strlen("this is a test")];
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Validate the parameters
if (argc != 2) {
printf("usage: %s server-name\n", argv[0]);
return 1;
}
// 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(argv[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;
}
char *sendbuf = new char[DEFAULT_BUFLEN]();
std::cout << "In the client ready to send a command..." << std::endl;
cin.getline(sendbuf, DEFAULT_BUFLEN);
int size;
for (size = 0; sendbuf[size] != '\0'; size++);
std::cout << sendbuf << std::endl;
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, size, 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// 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;
}
std::cout << "Command sent: " << sendbuf << std::endl;
// Receive until the peer 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 with error: %d\n", WSAGetLastError());
std::cout << iResult << std::endl;
} while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
I am creating a multi threaded server which will allow for multiple clients to join. But I have recently added this code to my client:
if (CTRL_CLOSE_EVENT == true)
{
send(ConnectSocket, (char*)quit, 1, 0);
iResult = shutdown(ConnectSocket, SD_BOTH);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
This should send a quit message whenever the console is closed, but whenever I close the console it throws a runtime library error and makes me abort. It comes up with recv() function failed and send() function failed, which means the socket hasn't shut down correctly.
Here is my server code:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <mutex>
#include <iostream>
#include <string>
#include "game.h"
#include <fstream>
// 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"
#define DEFAULT_IP "127.0.0.1 "
std::mutex MyMutex;
int ClientCount;
using namespace std;
std::ofstream outfile ("serverconfig.txt", std::ofstream::out | std::ofstream::app);
int callThread(SOCKET ClientSocket,int nCount)
{
MyMutex.lock();
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
int iResult, iSendResult;
// Receive until the peer shuts down the connection
printf("thread count: %d\n", nCount);
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult == 1)
{
cout << "Client " << nCount << " has left" << endl;
closesocket(ClientSocket);
nCount--;
}
if (iResult > 0)
{
printf("Bytes received: %d\n", iResult);
// 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)
{
nCount--;
printf("Connection closing...\n");
}
else {
printf("recv failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
MyMutex.unlock();
}
while (iResult > 0);
}
int __cdecl main(void)
{
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
ClientCount = 0;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
std::thread myThreads[100];
game game1;
string type;
string map;
int level;
int max;
int min;
//output server details to file
ofstream outfile;
outfile.open("serverconfig.txt");
outfile << DEFAULT_IP;
outfile << DEFAULT_PORT;
outfile.close();
//get start up data
/*cout << "please choose a type: 1: Deathmatch 2: Capture the flag 3: Blood Diamond" << endl;
cin >> type;
cout << "Please choose a map:" << endl;
cin >> map;
cout << "please choose a difficulty level between 1 - 3: " << endl;
cin >> level;
cout << "Please choose the max number of clients: " << endl;
cin >> max;
cout << "Please choose the min number of clients" << endl;
cin >> min; */
// 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);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
for (;;)
{
//creating a temp socket for accepting a connction
SOCKET ClientSocket;
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
else
{
myThreads[ClientCount] = std::thread(callThread, ClientSocket, ClientCount);
ClientCount++;
printf("normal count: %d\n", ClientCount);
if (ClientCount == 1)
{
cout << "Waiting for another Client to connect" << endl;
}
/*if (ClientCount >= 2)
{
cout << "Game" << type << "in progress" << endl;
}*/
}
}
// 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();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
system("PAUSE");
return 0;
}
And this is my client code:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
using namespace std;
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "this is a test";
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;
}
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
int quit = 1;
// Send and Receive until the peer 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 with error: %d\n", WSAGetLastError());
if (CTRL_CLOSE_EVENT == true)
{
send(ConnectSocket, (char*)quit, 1, 0);
iResult = shutdown(ConnectSocket, SD_BOTH);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
}
}
while (iResult > 0);
// 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();
system("PAUSE");
return 0;
}
I am using the source code from the MSDN for the C++ Winsock Server & Client, on the server side I am putting most of the code in functions and am having a access violation error. My complete source is below.
Any help would be great, thanks in advance!
This is my j420s,cpp file.
#include "j420s.h"
//Source From : MSDN Winsock Server Code.
//Original Source : https ://msdn.microsoft.com/en- us/library/windows/desktop/ms737593(v=vs.85).aspx
int __cdecl main(void) {
WSADATA wsaData;
int iResult = NULL;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *MySocketResult = NULL;
struct addrinfo MySocket;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = SocketInit(iResult, &wsaData);
if (iResult == 1){
return 1;
}
ZeroMemory(&MySocket, sizeof(MySocket));
MySocket.ai_family = AF_INET;
MySocket.ai_socktype = SOCK_STREAM;
MySocket.ai_protocol = IPPROTO_TCP;
MySocket.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = SocketAddrInfo(iResult, &MySocket, MySocketResult);
// Create a SOCKET for connecting to server
ListenSocket = SocketCreate(ListenSocket, MySocketResult);
if (ListenSocket == 1){
return 1;
}
// Setup the TCP listening socket
iResult = SocketBind(iResult, ListenSocket, MySocketResult);
if (iResult == 1) {
return 1;
}
iResult = SocketListen(iResult, ListenSocket, MySocketResult);
if (iResult == 1) {
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
closesocket(ListenSocket);
// Receive FOREVER!
while (1 == 1){
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
// Echo the buffer back to the sender
iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
} while (iResult > 0);
}
// 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();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
system("pause");
return 0;
}
int SocketAddrInfo(int iResult, addrinfo* MySocket, addrinfo* MySocketResult){
iResult = getaddrinfo(NULL, DEFAULT_PORT, MySocket, &MySocketResult);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
return iResult;
}
// Socket initialization
int SocketInit(int iResult, WSADATA *wsaData){
iResult = WSAStartup(MAKEWORD(2, 2), wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
return iResult;
}
// Socket create function to create a socket for connecting to our server.
SOCKET SocketCreate(SOCKET ListenSocket, addrinfo* MySocketResult){
ListenSocket = socket( MySocketResult->ai_family, MySocketResult- >ai_socktype, MySocketResult->ai_protocol );
if ( ListenSocket == INVALID_SOCKET ) {
printf("Socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(MySocketResult);
WSACleanup();
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
return ListenSocket;
}
// Socket bind function for binding our socket to an address for incoming connections.
int SocketBind(int iResult, SOCKET ListenSocket, addrinfo* MySocketResult) {
iResult = bind(ListenSocket, MySocketResult->ai_addr, (int)MySocketResult->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("Bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(MySocketResult);
closesocket(ListenSocket);
WSACleanup();
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
return iResult;
}
// Socket listen function to listen for incoming connections.
int SocketListen(int iResult, SOCKET ListenSocket, addrinfo* MySocketResult) {
freeaddrinfo(MySocketResult);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("Listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
return iResult;
}
// Socket accept connection function.
SOCKET SocketAcceptConnection(SOCKET ClientSocket, SOCKET ListenSocket) {
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
closesocket(ListenSocket);
return 0;
}
Here is my j420s.h file.
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using std::cout;
using std::endl;
// 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 "10187"
int SocketInit(int, WSADATA*);
int SocketAddrInfo(int, addrinfo*, addrinfo*);
SOCKET SocketCreate(SOCKET, addrinfo* );
int SocketBind(int, SOCKET, addrinfo* );
int SocketListen(int, SOCKET, addrinfo* );
SOCKET SocketAcceptConnection(SOCKET, SOCKET );
The access violation is somewhere in this function:
int SocketAddrInfo(int iResult, addrinfo* MySocket, addrinfo* MySocketResult){
iResult = getaddrinfo(NULL, DEFAULT_PORT, MySocket, &MySocketResult);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
return iResult;
}
I call the function like so:
iResult = SocketAddrInfo(iResult, &MySocket, MySocketResult);
I believe it's something to do with my pointers...
Again, any help would be great! Thanks again!
The result from getaddrinfo() will be thrown away on returning from the function SocketAddrInfo(), and MySocketResult in function main() remains NULL.
After that, this NULL is passed to SocketCreate(), and it is dereferenced via MySocketResult. It should cause crush.
You should pass a pointer to MySocketResult to SocketAddrInfo() and have getaddrinfo() modify it.
int SocketAddrInfo(int iResult, addrinfo* MySocket, addrinfo** MySocketResult){
iResult = getaddrinfo(NULL, DEFAULT_PORT, MySocket, MySocketResult);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
return iResult;
}
How to call:
iResult = SocketAddrInfo(iResult, &MySocket, &MySocketResult);
I am rather new to C++ and have run into a problem, when I connect to the server(using a browser) it sends a response fine and it shows up fine on the browser, however looking at the console it sent the webpage twice, a page view counter confirms this, from testing i am unsure of the order it runs.
loop listening for new connections:
while (true){
//create temp scoket for cconnetcion
SOCKET ClientSocket;
ClientSocket = INVALID_SOCKET;
// Accept the socket from the client when it tries to connect
ClientSocket = accept(ListenSocket, NULL, NULL);
printf("NEWCON" );
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ListenSocket);
WSACleanup();
return 104;
}
views += 1;
AfxBeginThread(RequestProsorses, (LPVOID)ClientSocket);
}
RequestProsorses function:
UINT RequestProsorses(LPVOID pParam){
printf("\n NEWREC");
SOCKET ClientSocket = (SOCKET)pParam;
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int conResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
std::string returnVal = "HTTP/1.x 200 OK \n Transfer-Encoding: chunked \n\n <html><body><b>Total Page Views:</b>";
conResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (conResult > 0) {
printf("Bytes received: %d\n", conResult);
//create response to user
returnVal += std::to_string(views) + "</body></html>";
//printf(returnVal.c_str());
// Send Responce to user
iSendResult = send(ClientSocket, returnVal.c_str(), returnVal.length(), 0);
if (iSendResult == SOCKET_ERROR) {
//printf("send failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ClientSocket);
WSACleanup();
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (conResult == 0){
printf("Connection closing...\n");
}
else {
printf("recv failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ClientSocket);
WSACleanup();
}
// shutdown the send half of the connection since no more data will be sent
conResult = shutdown(ClientSocket, SD_SEND);
if (conResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
}
closesocket(ClientSocket);
return 0;
}
Console output(form one view only):
NEWCONNEWCON
NEWREC
NEWRECBytes recived: 373
Bytes sent: 99
Bytes recevied: 287
Bytes sent:99
Hope that's enough info for you, if not i am happy to post more of course.
if statement to check foe end of header
for (int i = 0; i <= recvbuflen; i++){
if (recvbuf[i] == '\n' && (int)recvbuf[i + 1] == -52){
finished = true;
}
}
I have found the answer :), thanks to #JoachimPileborg and #MartinJames for there help!
Simply the browser was sending a second request and as the program does not check what page is being viewed(it simply sends the same page no matter what at the moment), it looked to me like it was doing the same thing twice just for one page request. the browser was trying to assess /favicon.ico just like its supposed too.
I have made changes to the code and although is by no means finished it works so here is the code if anyone's interested in the changes i made(in case there where other errors i fixed without realizing).
// HTMLtest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <iostream>
#include <thread>
#include <afxwin.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
int views = 0;
UINT RequestProsorses(LPVOID pParam){
printf("\n NEWREC");
SOCKET ClientSocket = (SOCKET)pParam;
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int conResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
std::string returnVal = "HTTP/1.x 200 OK \n Transfer-Encoding: chunked \n\n <html><body><b>Total Page Views:</b>";
bool finished = false;
do {
std::cout << "b";
conResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
for (int i = 0; i <= recvbuflen; i++){
if (recvbuf[i] == '\n' && (int)recvbuf[i + 1] == -52){
finished = true;
}
}
if (conResult > 0) {
}
else if (conResult == 0){
printf("Connection closing...\n");
}
else {
printf("recv failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ClientSocket);
}
} while (conResult > 0 && finished == false);
printf("Bytes received: %d\n", conResult);
std::cout << "RECIVED: " << recvbuf;
//create response to user
returnVal += std::to_string(views) + "</body></html>";
//printf(returnVal.c_str());
// Send Responce to user
iSendResult = send(ClientSocket, returnVal.c_str(), returnVal.length(), 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ClientSocket);
}
printf("Bytes sent: %d\n", iSendResult);
closesocket(ClientSocket);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
// Initialize Winsock
int IPresult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (IPresult != 0) {
printf("WSAStartup failed: %d\n", IPresult);
return 1;
}
struct addrinfo *result = NULL, *ptr = NULL, params;
ZeroMemory(¶ms, sizeof(params));
params.ai_family = AF_INET;
params.ai_socktype = SOCK_STREAM;
params.ai_protocol = IPPROTO_TCP;
params.ai_flags = AI_PASSIVE;
//resolve the IP address and port to used by the server
IPresult = getaddrinfo(NULL, "80", ¶ms, &result);
if (IPresult != 0) {
printf("getaddrinfo failed: %d\n", IPresult);
std::string blah;
std::cin >> blah;
WSACleanup();
return 100;
}
SOCKET ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
freeaddrinfo(result);
WSACleanup();
return 101;
}
// Setup the socket for HTTP
IPresult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (IPresult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 102;
}
//Free the memory allocated by "getadderinfo" as its no longe needed
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed with error: %ld\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ListenSocket);
WSACleanup();
return 103;
}
while (true){
//create temp scoket for cconnetcion
SOCKET ClientSocket;
ClientSocket = INVALID_SOCKET;
// Accept the socket from the client when it tries to connect
ClientSocket = accept(ListenSocket, NULL, NULL);
printf("NEWCON" );
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ListenSocket);
WSACleanup();
return 104;
}
views += 1;
AfxBeginThread(RequestProsorses, (LPVOID)ClientSocket);
}
// cleanup
//closesocket(ClientSocket);
WSACleanup();
return 0;
}
Sorry for how untidy it is :/