I'm now facing the problem of C++ winsock server programming for receiving messages from both TCP and UDP. In fact, UDP is used for receiving the job message from another server, while TCP receives messages from multiple RFID receivers.
So I've googled for days to see what approach I can use, and I found the followings:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms738620(v=vs.85).aspx
http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch08lev1sec15.html
However, I still cannot come up with the clear flow that how I can start the server application without selecting either TCP or UDP by the command line arguement i.e. I just want to start the winsock server program with creating both TCP and UDP sockets and then wait for connections.
So, according to the above two links, how can I do for the purpose I stated above i.e. how can I initialize the TCP and UDP sockets when I start the program and then go into the while loop for waiting the connections? Thanks!
Edited 20150918 4:12pm HKT
I've tried to combine the examples in two links provided above, but it is work for TCP while not in UDP. What is the problem for UDP according to the following server and client codes? Thanks!
server.cpp
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define STRICMP _stricmp
#define DEFAULT_PORT 5001
#define DEFAULT_PROTO SOCK_STREAM // TCP
void Usage(char *progname) {
fprintf(stderr, "Usage\n%s -e [endpoint] -i [interface]\n",
progname);
fprintf(stderr, "Where:\n\tendpoint is the port to listen on\n");
fprintf(stderr, "\tinterface is the ipaddr (in dotted decimal notation)");
fprintf(stderr, " to bind to\n");
fprintf(stderr, "Defaults are 5001 and INADDR_ANY\n");
WSACleanup();
exit(1);
}
int main(int argc, char **argv) {
char Buffer[128];
char *interface = NULL;
unsigned short port = DEFAULT_PORT;
int retval;
int fromlen;
int i;
int maxfdp1, nready;
struct sockaddr_in local, from;
WSADATA wsaData;
SOCKET listen_socket, udp_socket, msgsock;
fd_set SockSet;
/* Parse arguments */
if (argc >1) {
for (i = 1; i <argc; i++) {
if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
switch (tolower(argv[i][1])) {
case 'i':
interface = argv[++i];
break;
case 'e':
port = (unsigned short)atoi(argv[++i]);
break;
default:
Usage(argv[0]);
break;
}
}
else
Usage(argv[0]);
}
}
if ((retval = WSAStartup(0x202, &wsaData)) != 0) {
fprintf(stderr, "WSAStartup failed with error %d\n", retval);
WSACleanup();
return -1;
}
if (port == 0){
Usage(argv[0]);
}
local.sin_family = AF_INET;
local.sin_addr.s_addr = (!interface) ? INADDR_ANY : inet_addr(interface);
/*
* Port MUST be in Network Byte Order
*/
local.sin_port = htons(port);
listen_socket = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
if (listen_socket == INVALID_SOCKET){
fprintf(stderr, "socket() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if (bind(listen_socket, (struct sockaddr*)&local, sizeof(local))
== SOCKET_ERROR) {
fprintf(stderr, "TCP bind() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if (listen(listen_socket, 5) == SOCKET_ERROR) {
fprintf(stderr, "TCP listen() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
printf("TCP listen() established\n");
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (bind(udp_socket, (struct sockaddr*)&local, sizeof(local))
== SOCKET_ERROR) {
fprintf(stderr, "UDP bind() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
printf("UDP bind() established\n");
FD_ZERO(&SockSet);
maxfdp1 = max(listen_socket, udp_socket) + 1;
while (1) {
fromlen = sizeof(from);
FD_SET(listen_socket, &SockSet);
FD_SET(udp_socket, &SockSet);
if ((nready = select(maxfdp1, &SockSet, NULL, NULL, NULL)) < 0)
fprintf(stderr, "select() failed with error %d\n", WSAGetLastError());
if (FD_ISSET(listen_socket, &SockSet))
{
msgsock = accept(listen_socket, (struct sockaddr*)&from, &fromlen);
if (msgsock == INVALID_SOCKET)
{
fprintf(stderr, "accept() error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
printf("TCP msgsock=%d listen_socket=%d\n", msgsock, listen_socket);
printf("accepted connection from %s, port %d\n",
inet_ntoa(from.sin_addr),
htons(from.sin_port));
retval = recv(msgsock, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "recv() failed: error %d\n", WSAGetLastError());
closesocket(msgsock);
continue;
}
if (retval == 0) {
printf("Client closed connection\n");
closesocket(msgsock);
continue;
}
printf("Received %d bytes, data [%s] from client\n", retval, Buffer);
printf("Echoing same data back to client\n");
retval = send(msgsock, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "send() failed: error %d\n", WSAGetLastError());
}
printf("Terminating connection\n");
closesocket(msgsock);
}
else if (FD_ISSET(udp_socket, &SockSet))
{
retval = recvfrom(msgsock, Buffer, sizeof(Buffer), 0,
(struct sockaddr *)&from, &fromlen);
printf("Received datagram from %s\n", inet_ntoa(from.sin_addr));
if (retval == SOCKET_ERROR) {
fprintf(stderr, "recv() failed: error %d\n", WSAGetLastError());
closesocket(msgsock);
continue;
}
if (retval == 0) {
printf("Client closed connection\n");
closesocket(msgsock);
continue;
}
printf("Received %d bytes, data [%s] from client\n", retval, Buffer);
printf("Echoing same data back to client\n");
retval = sendto(msgsock, Buffer, sizeof(Buffer), 0,
(struct sockaddr *)&from, fromlen);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "send() failed: error %d\n", WSAGetLastError());
}
printf("UDP server looping back for more requests\n");
}
continue;
}
}
client.cpp
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_PORT 5001
#define DEFAULT_PROTO SOCK_STREAM // TCP
void Usage(char *progname) {
fprintf(stderr, "Usage\n%s -p [protocol] -n [server] -e [endpoint] \
-l [iterations]\n",
progname);
fprintf(stderr, "Where:\n\tprotocol is one of TCP or UDP\n");
fprintf(stderr, "\tserver is the IP address or name of server\n");
fprintf(stderr, "\tendpoint is the port to listen on\n");
fprintf(stderr, "\titerations is the number of loops to execute\n");
fprintf(stderr, "\t(-l by itself makes client run in an infinite loop,");
fprintf(stderr, " Hit Ctrl-C to terminate it)\n");
fprintf(stderr, "Defaults are TCP , localhost and 5001\n");
WSACleanup();
exit(1);
}
int main(int argc, char **argv) {
char Buffer[128];
char *server_name = "localhost";
unsigned short port = DEFAULT_PORT;
int retval, loopflag = 0;
int i, loopcount, maxloop = -1;
unsigned int addr;
int socket_type = DEFAULT_PROTO;
struct sockaddr_in server;
struct hostent *hp;
WSADATA wsaData;
SOCKET conn_socket;
if (argc >1) {
for (i = 1; i <argc; i++) {
if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
switch (tolower(argv[i][1])) {
case 'p':
if (!_stricmp(argv[i + 1], "TCP"))
socket_type = SOCK_STREAM;
else if (!_stricmp(argv[i + 1], "UDP"))
socket_type = SOCK_DGRAM;
else
Usage(argv[0]);
i++;
break;
case 'n':
server_name = argv[++i];
break;
case 'e':
port = (USHORT)atoi(argv[++i]);
break;
case 'l':
loopflag = 1;
if (argv[i + 1]) {
if (argv[i + 1][0] != '-')
maxloop = atoi(argv[i + 1]);
}
else
maxloop = -1;
i++;
break;
default:
Usage(argv[0]);
break;
}
}
else
Usage(argv[0]);
}
}
if ((retval = WSAStartup(0x202, &wsaData)) != 0) {
fprintf(stderr, "WSAStartup failed with error %d\n", retval);
WSACleanup();
return -1;
}
if (port == 0){
Usage(argv[0]);
}
//
// Attempt to detect if we should call gethostbyname() or
// gethostbyaddr()
if (isalpha(server_name[0])) { /* server address is a name */
hp = gethostbyname(server_name);
}
else { /* Convert nnn.nnn address to a usable one */
addr = inet_addr(server_name);
hp = gethostbyaddr((char *)&addr, 4, AF_INET);
}
if (hp == NULL) {
fprintf(stderr, "Client: Cannot resolve address [%s]: Error %d\n",
server_name, WSAGetLastError());
WSACleanup();
exit(1);
}
//
// Copy the resolved information into the sockaddr_in structure
//
memset(&server, 0, sizeof(server));
memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = htons(port);
conn_socket = socket(AF_INET, socket_type, 0); /* Open a socket */
if (conn_socket <0) {
fprintf(stderr, "Client: Error Opening socket: Error %d\n",
WSAGetLastError());
WSACleanup();
return -1;
}
printf("Client connecting to: %s\n", hp->h_name);
if (connect(conn_socket, (struct sockaddr*)&server, sizeof(server))
== SOCKET_ERROR) {
fprintf(stderr, "connect() failed: %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
loopcount = 0;
while (1) {
sprintf_s(Buffer, sizeof(Buffer), "This is a small test message [number %d]", loopcount++);
retval = send(conn_socket, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "send() failed: error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
printf("Sent Data [%s]\n", Buffer);
retval = recv(conn_socket, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "recv() failed: error %d\n", WSAGetLastError());
closesocket(conn_socket);
WSACleanup();
return -1;
}
if (retval == 0) {
printf("Server closed connection\n");
closesocket(conn_socket);
WSACleanup();
return -1;
}
printf("Received %d bytes, data [%s] from server\n", retval, Buffer);
if (!loopflag){
printf("Terminating connection\n");
break;
}
else {
if ((loopcount >= maxloop) && (maxloop >0))
break;
else
Sleep(2000);
}
}
closesocket(conn_socket);
WSACleanup();
}
In server.cpp where you're reading/writing the UDP socket:
else if (FD_ISSET(udp_socket, &SockSet))
{
retval = recvfrom(msgsock, Buffer, sizeof(Buffer), 0,
(struct sockaddr *)&from, &fromlen);
printf("Received datagram from %s\n", inet_ntoa(from.sin_addr));
...
printf("Echoing same data back to client\n");
retval = sendto(msgsock, Buffer, sizeof(Buffer), 0,
(struct sockaddr *)&from, fromlen);
if (retval == SOCKET_ERROR) {
fprintf(stderr, "send() failed: error %d\n", WSAGetLastError());
}
printf("UDP server looping back for more requests\n");
}
You're using msgsock in your recv and send calls (as well as closesocket), which you use for the accepted TCP socket, instead of udp_socket.
Change msgsock to udp_socket in this block and it should work.
Related
If you try and run my script you can see that GetQueuedCompletionStatus not will block after second wsarecv call. I don't understand why this code won't work.
The code is a bit messy but quite simple so it should work.
server:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <thread>
#include <iostream>
using namespace std;
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
WSADATA wsaData;
int iResult;
HANDLE CompletionPort;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[200];
DWORD BytesSEND;
DWORD BytesRECV;
DWORD RecvBytes;
sockaddr_in local;
DWORD Flags;
int iSendResult;
void serverWorkerThread() {
OVERLAPPED lpol2;
DWORD Flags = 0;
DWORD BytesTransferred;
DWORD is = 0;
DWORD sentBytes;
bool kage = 0;
WSABUF wsabuf;
CHAR Buffer2[200];
while (true) {
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, &is, (LPOVERLAPPED*)& lpol2, INFINITE) == 0)
{
printf("GetQueuedCompletionStatus() failed with error %d\n", GetLastError());
}
else
printf("GetQueuedCompletionStatus() is OK!\n");
cout << DataBuf.buf << endl;
cout << is;
DataBuf.len = 14;
ZeroMemory(&(Overlapped), sizeof(OVERLAPPED));
if (WSASend(ClientSocket, &DataBuf, 1, &sentBytes, 0,
NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
}
}
else
printf("WSASend() is OK!\n");
ZeroMemory(&(lpol2), sizeof(OVERLAPPED));
wsabuf.buf = Buffer2;
wsabuf.len = 200;
BytesTransferred = 0;
is = 0;
ZeroMemory(&(Overlapped), sizeof(OVERLAPPED));
Flags = 0;
if (WSARecv(ClientSocket, &wsabuf, 1, &RecvBytes, &Flags, &Overlapped, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
}
}
else printf("WSARecv() is OK!\n");
}
}
int __cdecl main(void)
{
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
//Now we populate the sockaddr_in structure
local.sin_family = AF_INET; //Address family
local.sin_addr.s_addr = INADDR_ANY; //Wild card IP address
local.sin_port = htons((u_short)20248); //port to use
// Create a SOCKET for connecting to server
ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, (sockaddr*)& local, sizeof(local));
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
DataBuf.len = 2000;
DataBuf.buf = Buffer;
thread t1(serverWorkerThread);
t1.detach();
DWORD iss = 34543;
while (TRUE)
{
ClientSocket = WSAAccept(ListenSocket, NULL, NULL, NULL, 0);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
if (CreateIoCompletionPort((HANDLE)ClientSocket, CompletionPort, 43343, 0) == NULL)
{
printf("CreateIoCompletionPort() failed with error %d\n", GetLastError());
return 1;
}
else
printf("CreateIoCompletionPort() is OK!\n");
Flags = 0;
if (WSARecv(ClientSocket, &DataBuf, 1, &RecvBytes, &Flags, &Overlapped, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return 1;
}
}
else printf("WSARecv() is OK!\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();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
client:
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
// 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")
using namespace std;
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int __cdecl main(int argc, char** argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
SOCKADDR_IN ServerAddr;
// Server/receiver port to connect to
unsigned int Port = 20248;
//struct addrinfo* result = NULL,
// * ptr = NULL,
// hints;
const char* sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
cout << sendbuf << endl;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
// Create a SOCKET for connecting to server
ConnectSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 2;
}
// IPv4
ServerAddr.sin_family = AF_INET;
// Port no.
ServerAddr.sin_port = htons(Port);
// The IP address
ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR*)& ServerAddr, sizeof(ServerAddr));
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 3;
}
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 4;
}
// 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 5;
}
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 6;
}
// 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());
} while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
i found the problem:
the clients shoutdown the connetion which made the GetQueuedCompletionStatus keep running
I'm trying to use two threads to run a server and a client.
I use a semaphore to block the client thread from doing too much before the server has been set up (ListenSocket, etc.).
When The server gets far enough, I use ReleaseSemaphore() but it returns an Invalid Handle error.
I've read that there are many possible issues which can be the source of this error.
The exact line is if (ReleaseSemaphore(semaphore, 1, NULL)){} which can be found about 55% of the way into the Server.cpp file
Header.h:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <process.h>
unsigned int __stdcall servermain(void*);
unsigned int __stdcall clientmain(void*);
static HANDLE semaphore;
Source.cpp:
#include "Header.h"
int main(int argc, char* argv[])
{
HANDLE serverHandle, clientHandle;
semaphore = CreateSemaphore(
NULL,
0, //initial count
1, //max count
NULL);
if (semaphore == NULL){
printf("CreateSemaphore error: %d\n", GetLastError());
return 1;
}
/*call to the methods in the Client and Server files*/
serverHandle = (HANDLE)_beginthreadex(0, 0, &servermain, 0, 0, 0);
clientHandle = (HANDLE)_beginthreadex(0, 0, &clientmain, 0, 0, 0);
WaitForSingleObject(serverHandle, INFINITE);
WaitForSingleObject(clientHandle, INFINITE);
CloseHandle(serverHandle);
CloseHandle(clientHandle);
CloseHandle(semaphore);
return 0;
}
Server.cpp:
#include "Header.h"
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
unsigned int __stdcall servermain(void* data)
{
printf("SERVER STARTED. Thread: %i\n", GetCurrentThreadId());
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo
*result = NULL,
hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); //initiates the use of the Winsock DLL
if (iResult != 0) {
printf("%i Server:\t", GetCurrentThreadId());
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
//////////////////////////////////////
// Creating a Socket for the Server //
//////////////////////////////////////
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, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("%i Server:\t", GetCurrentThreadId());
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for the server to listen for client connections
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("%i Server:\t", GetCurrentThreadId());
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
//////////////////////
// Binding a Socket //
//////////////////////
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("%i Server:\t", GetCurrentThreadId());
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
char answer = 'y'; // char answer[8]; // char *answer = "";
do{
printf("%i Server:\t", GetCurrentThreadId());
printf("Would you like to wait for client?(Y/N)\t");
answer = getchar(); // fgets(answer, 1, stdin);
printf("%c\n", answer);
} while (answer != 'y' && answer != 'n'); // double quotes "" are for c-strings. single quotes '' are for chars.
if (answer == 'n'){
return 1;
}
else printf("%i Server:\tListening for a client...\n", GetCurrentThreadId());
freeaddrinfo(result);
printf("Semaphore value: %i\n", semaphore);
//Now that the server is running, signal the semaphore to allow client to connect.
if (ReleaseSemaphore(semaphore, 1, NULL)) //ReleaseSemaphore() returns a bool value
{
printf("%i Server: Semaphore Released\n", GetCurrentThreadId());
}
else
{
printf("Server Release Semaphore error: %d\n", GetLastError());
printf("Server Semaphore value: %i\n", semaphore);
return 1;
}
///////////////////////////
// Listening on a Socket //
///////////////////////////
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("%i Server:\t", GetCurrentThreadId());
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
////////////////////////////
// Accepting a Connection //
////////////////////////////
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("%i Server:\t", GetCurrentThreadId());
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// No longer need server socket
closesocket(ListenSocket); // This will need to be changed if multiple clients shall be allowed
//////////////////////////////////////////////
// Receiving and Sending Data on the Server //
//////////////////////////////////////////////
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("%i Server:\t", GetCurrentThreadId());
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); //why close a socket if something doesn't send correctly?
WSACleanup();
return 1; //kills main()
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup(); //function terminates use of the Winsock 2 DLL (Ws2_32.dll)
return 1;
}
} while (iResult > 0);
// shutdown the send half of the connection since no more data will be sent
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("%i Server:\t", GetCurrentThreadId());
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
_endthreadex(0); //end thread within the thread.
return 0;
}
Client.cpp:
#include "Header.h"
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
unsigned int __stdcall clientmain(void* data)
{
printf("CLIENT STARTED. Thread: %i\n", GetCurrentThreadId());
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;
// 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("%i Client:\t", GetCurrentThreadId());
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
printf("Client winsock initialized\n");
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;
}*/
printf("%i Client: before semaphore\n", GetCurrentThreadId());
//Wait for Server to be up and running
bool cont = TRUE;
while (cont)
{
DWORD returnval = WaitForSingleObject(semaphore, 0L); // 0 vs 0L ?
//printf("Semaphore value: %i\n", semaphore);
switch (returnval)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("Thread %d: wait timed out\n", GetCurrentThreadId());
break;
}
}
printf("%i Client: after semaphore\n", GetCurrentThreadId());
// 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("%i Client:\t", GetCurrentThreadId());
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("%i Client:\t", GetCurrentThreadId());
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("%i Client:\t", GetCurrentThreadId());
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("%i Client:\t", GetCurrentThreadId());
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
printf("%i Client:\t", GetCurrentThreadId());
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());
} while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
printf("%i Client:\t", GetCurrentThreadId());
printf("\nReturn to close.\n");
getchar(); //allow user to do see screen before shutting down
_endthreadex(0);
return 0;
}
You declare semaphore as a static HANDLE in header.h. That means that every source module that includes "header.h" will have its own copy of that variable. Thus, the semaphore in main.cpp that holds the Windows semaphore handle is a different variable than the semaphore referenced in server.cpp.
Remove the static from the declaration in header.h, replace it with extern, and add a definition for it in main.cpp.
I've been doing the Winsock tutorials and following it exactly. I can't seem to get either send() or recv() to function properly. I have a basic Server and Client program set up, and the connection is being made, but the Server isn't sending a message to the Client. Using the Telnet client also doesn't receive a response from the server. I'm not really sure what's happening, and all the questions I looked at were not basic or had stuff I couldn't really understand what they were doing.
Server.cpp
#include<WinSock2.h>
#include <io.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib") //winsock library
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
sockaddr_in server, client;
int c;
char *message;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
else
printf("Initialised.\n");
//create a socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
return 2;
}
else
printf("Socket created.\n");
//prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.S_un.S_addr = INADDR_ANY;
server.sin_port = htons(8888);
//bind the socket
if (bind(s, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : &d", WSAGetLastError());
return 3;
}
else
puts("Bind done");
//listen
listen(s, 3);
//accept an incoming connection
puts("Waiting for incoming connections...");
c = sizeof(sockaddr_in);
while (new_socket = accept(s, (sockaddr *)&client, &c) != INVALID_SOCKET)
{
printf("Connect successful...\n");
//reply to the client
message = "Hello Client, I have recieved your connection, but I have to go now, bye!\n";
send(new_socket, message, strlen(message), 0);
puts("Message sent.\n");
}
if (new_socket == INVALID_SOCKET)
{
printf("accept() failed with error code : %d", WSAGetLastError());
return 4;
}
//close the socket
closesocket(s);
WSACleanup();
return 0;
}
Client.cpp
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <IPHlpApi.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char *argv[])
{
//intialize variables
WSADATA wsa;
char ip[100] = "192.168.1.117";
SOCKET s;
sockaddr_in server;
char *message, server_reply[75];
int recv_size;
//initialize Winsock
printf("\nInitialising Winsock...\n");
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//create the socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
return 3;
}
printf("Socket created.\n");
server.sin_addr.S_un.S_addr = inet_addr(ip);
server.sin_family = AF_INET;
server.sin_port = htons(8888);
//connect to the server
if (connect(s, (sockaddr *)&server, sizeof(server)) < 0)
{
puts("connect error");
return 4;
}
else
{
printf("Connect successful");
recv_size = recv(s, server_reply, 75, 0);
}
if (recv_size <= 0)
{
puts("recv() failed\n");
}
else
{
//add a NULL terminating character to make it a proper string before printing
server_reply[recv_size] = '\0';
puts(server_reply);
}
getchar();
//close the socket
closesocket(s);
WSACleanup();
return 0;
}
The client also fails to print the "recv() failed" line; it's like it's stuck at the recv() call.
On the server side:
you are not checking the return value of listen() for error.
you are not resetting c on each call to accept(), and you are not calling closesocket() on each client that is accepted.
you are not checking the return value of send() for error.
Try this instead:
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib") //winsock library
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
sockaddr_in server, client;
int c, res, messagelen;
const char *message;
printf("\nInitializing Winsock...");
res = WSAStartup(MAKEWORD(2,2), &wsa);
if (res != 0)
{
printf("Failed. Error: %d\n", res);
return 1;
}
printf("Initialized.\n");
//create a socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket. Error: %d\n", WSAGetLastError());
return 2;
}
printf("Socket created.\n");
//prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.S_un.S_addr = INADDR_ANY;
server.sin_port = htons(8888);
//bind the socket
if (bind(s, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed. Error: &d", WSAGetLastError());
return 3;
}
printf("Bind done.\n");
//listen
if (listen(s, 3) == SOCKET_ERROR)
{
printf("Listen failed. Error: &d", WSAGetLastError());
return 4;
}
printf("Listening.\n");
//accept incoming connections
printf("Waiting for incoming connections...\n");
do
{
c = sizeof(sockaddr_in);
new_socket = accept(s, (sockaddr *)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("Failed to accept a client. Error: %d\n", WSAGetLastError());
return 5;
}
printf("Client connected...\n");
//reply to the client
message = "Hello Client, I have received your connection, but I have to go now, bye!\n";
messagelen = strlen(message);
do
{
res = send(new_socket, message, messagelen, 0);
if (res == SOCKET_ERROR)
{
printf("Failed to send message. Error: %d\n", WSAGetLastError());
break;
}
message += res;
messagelen -= res;
}
while (messagelen > 0);
if (messagelen == 0)
printf("Message sent.\n");
//close the client socket
closesocket(new_socket);
}
while (true);
//close the server socket
closesocket(s);
WSACleanup();
return 0;
}
On the client side, the only real problem I see is your recv() call has a potential buffer overflow waiting to happen, since you ask it to read 75 bytes, and that is the exact size of your buffer. It just happens that your server is only sending 74 bytes max, but if it ever sent more, you could overflow the buffer when appending the '\0' terminator to it.
So, either:
call recv() with sizeof(server_reply)-1 as the buffer size, to give yourself room for the added terminator:
recv_size = recv(s, server_reply, sizeof(server_reply)-1, 0);
use printf() instead of puts() so you don't need to null-terminate the buffer at all when printing it to the console. You can pass recv_size as a parameter to limit the amount of text being printed:
//server_reply[recv_size] = '\0';
//puts(server_reply);
printf("%.*s", recv_size, server_reply);
From the MSDN documentation on closesocket():
Note To assure that all data is sent and received on a connection, an application should call shutdown before calling closesocket (see Graceful shutdown, linger options, and socket closure for more information). Also note, an FD_CLOSE network event is not posted after closesocket is called.
Basically the data you have sent was still pending when you closed the socket.
I made a socket I've slowly been adding on to for about a week now and I've come across a problem. I set up a port on my local 127.0.0.1 ip address to allow me to connect to my own computer and when I recieve the response from my computer it says "400 Bad Request. The request is badly formed.". I think it has to do with the http header information I send via the send(); function. sendbuf Contains the header information to be sent. Here's my code:
#include <windows.h>
#include <winsock2.h>
#include <conio.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define SCK_VERSION2 0x0202
#define DEFAULT_BUFLEN 2000
#define DEFAULT_PORT 27015
namespace Globals{
extern string input = "";
}
using namespace Globals;
void USERNAME() {
do {
printf("USERNAME: \t");
getline(cin, input);
if ( input == "User Name" ) {
break;
}
} while(true);
}
void PASSWORD() {
do {
printf("PASSWORD: \t");
getline(cin, input);
if ( input == "Password" ) {
break;
}
USERNAME();
} while(true);
}
int whole() {
USERNAME();
PASSWORD();
//----------------------
// Declare and initialize variables.
WSADATA wsaData;
int iResult;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char name[500] = "";
char ipADDRESS[500] = "";
char sPORT[500] = "";
sockaddr_in sName;
int sNameSize = sizeof(sName);
char *sendbuf = "GET /TR HTTP/1.1 \nHost: net.tutsplus.com \nUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729) \nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 \nAccept-Language: en-us,en;q=0.5 \nAccept-Encoding: gzip,deflate \nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 \nKeep-Alive: 300 \nConnection: keep-alive \nCookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120 \nPragma: no-cache \nCache-Control: no-cache";
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN; //208.109.181.178
int WSAERROR = WSAGetLastError();
//system("color 04");
//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %i\n", WSAGetLastError() );
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
printf("IP ADDRESS: \n");
cin >> ipADDRESS;
printf("PORT: \n");
cin >> sPORT;
u_short PORT = strtoul(sPORT, NULL, 0);
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(ipADDRESS); //74.125.196.191
clientService.sin_port = htons(PORT);
//----------------------
// Connect to server.
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
if ( iResult == SOCKET_ERROR) {
closesocket (ConnectSocket);
printf("Unable to connect to server: %i\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
//Get local host name
iResult = gethostname(name, sizeof(name));
if (iResult == NO_ERROR) {
printf("Host Name: %s\n", name);
}
else if (iResult == SOCKET_ERROR) {
printf("Could not resolve host name: %i", WSAGetLastError());
}
//------------------------
//Get peer name
iResult = getpeername(ConnectSocket, (struct sockaddr*)&sName, &sNameSize);
if (iResult == NO_ERROR)
printf("Peer Name: %s\n", inet_ntoa(sName.sin_addr));
else if (iResult == SOCKET_ERROR)
printf("Could not get peer name: %i\n", WSAGetLastError());
//-------------------------
// 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;
}
else
printf("Bytes Sent: %i\n", iResult);
//-----------------------------
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %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 ) {
printf("Bytes received: %d\n", iResult); //printf("Bytes received: %d\n", iResult);
printf("From server: %s\n", recvbuf);
}
else if ( iResult == 0 )
printf("Connection closed\n");
else if (WSAERROR == WSAETIMEDOUT)
printf("recv failed: WSAETIMEDOUT\n");
printf("Do you want to disconnect? (Y/N) \n");
cin >> input;
if ( input == "Y"||"y" ) {
break;
}
else if ( input == "N"||"n" ) {
break;
}
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
system("PAUSE");
return 0;
}
int main() {
do {
whole();
} while( input != "N"||"n" );
}
I figured it out, in sendbuf I was putting an invalid host name. XD
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 :/