-
Troubles with Sockets
Hello together,
this is my first thread here, but i think there will be some more ;)
Ok, here's my problem:
I've written a simple client programm, which sends data to a server every 5 minutes or so.
Because of this small amount of data, i always reopen a socket. But this socket doesn't close propertly, the connection stays in state TIME_WAIT.
Every time i reopen a Socket, the programm also allocates about 8-12 kB of memory, and never frees it again.
I will post my network code here, and i hope some of you guys are able to help me.
Code:
#include "stdafx.h"
#include "NetworkHandler.h"
#define NETWORK_ERROR -1
#define NETWORK_OK 0
#define SD_SEND 1
#define SD_RECEIVE 1
/* Prototypes */
void ReportError(int errorCode, const char *whichFunc);
char buffer[256]; //Buffer for the message
char errorMsg[92]; //Buffer for the errorMessage
WORD sockVersion;
WSADATA wsaData;
LPHOSTENT hostEntry;
SOCKADDR_IN serverInfo;
SOCKET theSocket;
LINGER theLinger;
int nret;
int connState;
/*
* Main function, calls the other functions.
*/
int connectToServer(void) {
connState = 0;
connState = initConnection();
connState = sendMessage();
closeConnection();
return connState;
}
/*
* Initialize the connection, by setting the server name and port
* Open the connection
*/
int initConnection(){
sockVersion = MAKEWORD(1, 1);
WSAStartup(sockVersion, &wsaData);
hostEntry = gethostbyname("127.0.0.1");
if (!hostEntry) {
nret = WSAGetLastError();
ReportError(nret, "gethostbyname()");
WSACleanup();
return NETWORK_ERROR;
}
theSocket = socket(AF_INET,
SOCK_STREAM,
IPPROTO_TCP);
theLinger.l_onoff = 1;
theLinger.l_linger = 0;
setsockopt(theSocket, SOL_SOCKET, SO_LINGER, (char *) &theLinger, sizeof(LINGER));
if (theSocket == INVALID_SOCKET) {
nret = WSAGetLastError();
ReportError(nret, "socket()");
WSACleanup();
return NETWORK_ERROR;
}
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
serverInfo.sin_port = htons(13);
nret = connect(theSocket,
(LPSOCKADDR)&serverInfo,
sizeof(struct sockaddr));
if (nret == SOCKET_ERROR) {
nret = WSAGetLastError();
ReportError(nret, "connect()");
closesocket(theSocket);
WSACleanup();
return NETWORK_ERROR;
}
return 0;
}
/*
* Send data method
*/
int sendMessage(){
ZeroMemory(buffer, 256);
wsprintf(buffer, "Some message");
nret = send(theSocket,
buffer,
strlen(buffer),
0);
if (nret == SOCKET_ERROR) {
closeConnection();
return NETWORK_ERROR;
}
return 0;
}
/*
* Close Socket
*/
void closeConnection(){
int b;
char buf[256];
WSACancelBlockingCall();
shutdown(theSocket, SD_SEND);
while ((b = recv(theSocket, buf, 256, 0)) != 0)
if (b == SOCKET_ERROR)
break;
shutdown(theSocket, SD_RECEIVE);
closesocket(theSocket);
WSACleanup();
}
void ReportError(int errorCode, const char *whichFunc) {
ZeroMemory(errorMsg, 92);
sprintf(errorMsg, "Call to %s returned error %d!", (char *)whichFunc, errorCode);
MessageBox(NULL, errorMsg, "NetworkError", MB_OK);
}
I have this problem since a few days so i hope somebody has a solution for this. Thank you.
-
Been a while but I remember having a similar problem....
have you tried setsockopt() with a SO_DONTLINGER?
-
Well, the connections closing now, i had to set the LINGER on the serverside too. But thanks for your answer.
But i still have the problem of the memory leak. Every time a connection is closed, the memory is left allocated.
Any suggestions about that?
I dont really have a clue why this is happening.
-
Looks OK to me ...... but been a while since I did sockets.
You could.......
Check the return from WSACleanup()
and look at bind()
-
how is this code called? You don't want to call WSAStartup and WSACleanup over and over, only call them once at the start and end of the program.
-
This Code is called over a Timer every 5 minutes or so.
Well i'll try to call WSAStartup() and WSACleanup() only once, but i dont think this will solve my problem. The problem seems to be the socket. :rolleyes:
Edit: I have changed my code as you said, and it seems to work now. Thank you very mutch, i browsed the net for a solution of this for many hours ;)
-
Hello cornholio,
I played with your code and I have questions about it, but rather than ask you, I thought it might be easier if I posted a simple client/server example, then you could see if maybe your code could be corrected. (You probably don't need this server, but I give it anyway.)
Here goes...the Client simply repeatedly sets up/ breaks down a connection.
The simple Client:
Code:
// I compile/link with gcc (let me know if you want the vc compile/link commands)
//gcc myclient.c -lws2_32 -o myclient.exe
#include <windows.h>
#include <stdio.h>
#include <winsock.h>
#define DEST_IP_ADDR "127.0.0.1"
#define PORT (u_short) 13
int main()
{
#define MAXBUFLEN 256
WSADATA Data;
SOCKET destSocket;
SOCKADDR_IN destSockAddr;
unsigned long destAddr;
int status;
int numsnt;
char sendText[MAXBUFLEN] = "Some message";
while(1) {
status = WSAStartup(MAKEWORD(1, 1), &Data);
if (status != 0)
{ printf("WSAStartup unsuccessful\n"); }
destSocket = socket(AF_INET, SOCK_STREAM, 0);
if (destSocket == INVALID_SOCKET) {
printf("socket unsuccessful\n");
status = WSACleanup();
if (status == SOCKET_ERROR)
{ printf("WSACleanup unsuccessful\n"); }
return(1);
}
destAddr = inet_addr(DEST_IP_ADDR);
memcpy(&destSockAddr.sin_addr, &destAddr, sizeof(destAddr));
destSockAddr.sin_port = htons(PORT);
destSockAddr.sin_family = AF_INET;
printf("Trying to connect to IP Address: %s\n",DEST_IP_ADDR);
status = connect(destSocket, (LPSOCKADDR) &destSockAddr, sizeof(destSockAddr));
if (status == SOCKET_ERROR) {
printf("connect unsuccessful\n");
status = closesocket(destSocket);
if (status == SOCKET_ERROR)
{ printf("closesocket unsuccessful\n"); }
status = WSACleanup();
if (status == SOCKET_ERROR)
{ printf("WSACleanup unsuccessful\n"); }
return(1);
}
printf("Connected...\n");
//printf("Type text to send: ");
//gets(sendText);
numsnt = send(destSocket, sendText, strlen(sendText) + 1, 0);
if (numsnt != (int)strlen(sendText) + 1) {
printf("Connection terminated.\n");
status = closesocket(destSocket);
if (status == SOCKET_ERROR)
{ printf("closesocket unsuccessful\n"); }
status = WSACleanup();
if (status == SOCKET_ERROR)
{ printf("WSACleanup unsuccessful\n"); }
return(1);
}
status = closesocket(destSocket);
if (status == SOCKET_ERROR)
{ printf("closesocket unsuccessful\n"); }
status = WSACleanup();
if (status == SOCKET_ERROR)
{ printf("WSACleanup unsuccessful\n"); }
printf("Connection terminated.\n");
//Sleep(10000); // wait 10 seconds
} /* while */
}
The simple Server:
Code:
//gcc myserver.c -lws2_32 -o myserver.exe
#include <windows.h>
#include <stdio.h>
#include <winsock2.h>
#include <process.h>
#define NO_FLAGS_SET 0
#define PORT (u_short) 13
#define MAXBUFLEN 256
VOID talkToClient(VOID *cs) {
char buffer[MAXBUFLEN];
int status;
int numsnt;
int numrcv;
SOCKET clientSocket = (SOCKET)cs;
while(1) {
numrcv = recv(clientSocket, buffer, MAXBUFLEN, NO_FLAGS_SET);
if ((numrcv == 0) || (numrcv == SOCKET_ERROR)) {
printf("Connection terminated\n");
break;
}
//printf("n= %i",numrcv);
buffer[numrcv] = '\0';
printf("Received: %s\n",buffer);
//_strupr(buffer);
numsnt = send(clientSocket, buffer, strlen(buffer) + 1, NO_FLAGS_SET);
if (numsnt != (int)strlen(buffer) + 1) {
printf("Connection terminated.");
break;
}
} /* while */
status = shutdown(clientSocket, 2);
if (status == SOCKET_ERROR)
{ printf("shutdown unsuccessful"); }
status = closesocket(clientSocket);
if (status == SOCKET_ERROR)
{ printf("closesocket unsuccessful"); }
}
int main(VOID) {
WSADATA Data;
SOCKADDR_IN serverSockAddr;
SOCKADDR_IN clientSockAddr;
SOCKET serverSocket;
SOCKET clientSocket;
int addrLen=sizeof(SOCKADDR_IN);
int status;
DWORD threadID;
/* initialize the Windows Socket DLL */
status=WSAStartup(MAKEWORD(1, 1), &Data);
if (status != 0) {
printf("WSAStartup unsuccessful");
return(1);
}
memset(&serverSockAddr, 0, sizeof(serverSockAddr));
serverSockAddr.sin_port = htons(PORT);
serverSockAddr.sin_family = AF_INET;
serverSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET) {
printf("ERROR: socket unsuccessful");
status = WSACleanup();
if (status == SOCKET_ERROR)
{ printf("WSACleanup unsuccessful"); }
return(1);
}
status = bind(serverSocket, (LPSOCKADDR) &serverSockAddr, sizeof(serverSockAddr));
if (status == SOCKET_ERROR)
{ printf("bind unsuccessful"); }
status = listen(serverSocket, 1);
if (status == SOCKET_ERROR)
{ printf("listen unsuccessful"); }
while(1) {
clientSocket = accept(serverSocket, (LPSOCKADDR) &clientSockAddr, &addrLen);
if (clientSocket == INVALID_SOCKET) {
printf("Unable to accept connection");
return(1);
}
threadID = _beginthread(talkToClient, 0, (VOID *)clientSocket);
if (threadID == -1) {
printf("Unable to create thread");
status = closesocket(clientSocket);
if (status == SOCKET_ERROR)
{ printf("closesocket unsuccessful"); }
}
}
}