Click here to Skip to main content
14,734,709 members
Please Sign up or sign in to vote.
1.60/5 (2 votes)
See more:
Hello.
I created a telnet server based on this code from
[c/c++] How To Code A Multi-client Server In C\++ Using Threads - Tutorials - rohitab.com - Forums[^]


#include <windows.h>
#include  <stdlib.h>
#include <stdio.h>
#include <winsock.h>
#include "mingw.thread.h"

// our thread for recving commands
DWORD WINAPI receive_cmds(LPVOID lpParam) 
{
// Here I changed for our needs ! its a warehouse management system.  
  printf("thread created\r\n");
  
  // set our socket to the socket passed in as a parameter   
  SOCKET current_client = (SOCKET)lpParam; 
  
  // buffer to hold our recived data
  char buf[100];
  // buffer to hold our sent data
  char sendData[100];
  // for error checking 
  int res;
  
  // our recv loop
  while(true) 
  {
	 res = recv(current_client,buf,sizeof(buf),0); // recv cmds
	 
	 Sleep(10);
	 
	 if(res == 0)
	 {
	  MessageBox(0,"error","error",MB_OK);
	  closesocket(current_client);
	  ExitThread(0);
	 }
	 
	 if(strstr(buf,"hello"))
	 { // greet this user
	   printf("\nrecived hello cmd");
	   
	   strcpy(sendData,"hello, greetz from KOrUPt\n");
	   Sleep(10);
	   send(current_client,sendData,sizeof(sendData),0); 
	 }								
	 else if(strstr(buf,"bye"))   
	 { // dissconnected this user
	   printf("\nrecived bye cmd\n");
	   
	   strcpy(sendData,"cya\n");
	   Sleep(10);
	   send(current_client,sendData,sizeof(sendData),0);
 
	  // close the socket associted with this client and end this thread
	   closesocket(current_client);
	   ExitThread(0);
	 }
	 else
	 {
	   strcpy(sendData,"Invalid cmd\n");
	   Sleep(10);
	   send(current_client,sendData,sizeof(sendData),0);
	 }
	 
	 // clear buffers
	   strcpy(sendData,"");
	   strcpy(buf,"");
   }
}   

int main()
{
 printf("Starting up multi-threaded TCP server by KOrUPt\r\n");
 
 // our masterSocket(socket that listens for connections)
 SOCKET sock;
 
 // for our thread
 DWORD thread; 
 
 WSADATA wsaData;
 sockaddr_in server;
 
 // start winsock
 int ret = WSAStartup(0x101,&wsaData); // use highest version of winsock avalible
 
 if(ret != 0)
 {
	return 0;
 }
  
 // fill in winsock struct ... 
 server.sin_family=AF_INET; 
 server.sin_addr.s_addr=INADDR_ANY; 
 server.sin_port=htons(123); // listen on telnet port 23
 
 // create our socket
 sock=socket(AF_INET,SOCK_STREAM,0); 
 
 if(sock == INVALID_SOCKET)
 {
	return 0;
 }
  
 // bind our socket to a port(port 123) 
 if( bind(sock,(sockaddr*)&server,sizeof(server)) !=0 )
 {
	return 0;
 }
  
 // listen for a connection  
 if(listen(sock,5) != 0)
 {
	return 0;
 }
 
 // socket that we snedzrecv data on
 SOCKET client;
 
 sockaddr_in from;
 int fromlen = sizeof(from); 
  
 // loop forever 

 while ((client = accept(sock, (struct sockaddr*)&from,&fromlen))!= INVALID_SOCKET) 
{
  // accept connections
  client = accept(sock,(struct sockaddr*)&from,&fromlen);
  printf("Client connected\r\n");
  
  // create our recv_cmds thread and parse client socket as a parameter
  // CreateThread(NULL, 0,receive_cmds,(LPVOID)client, 0, &thread);   
// Reaplaced CreateThread with
std::thread th_client(receive_cmds,(LPVOID)client);
 }
 
 // shutdown winsock
 closesocket(sock); 
 WSACleanup(); 
 
 // exit
 return 0;
}


What I have tried:

CPU usage increasing over time.
Not from memory leak.
Please help me
Posted
Updated 3-Mar-20 5:30am
v2
Comments
Shao Voon Wong 3-Mar-20 19:34pm
   
You are calling accept twice! First call in the while condition and second call is in the while loop. Remove one of them.
Member 4099447 5-Mar-20 11:01am
   
I forgot to comment out second accept.in my code it is.
Number of threads not increase do to the fact that we have only 7 hand held devices that communicate with the server
Stefan_Lang 5-Mar-20 11:06am
   
Fine, then tell it to your code.
Member 4099447 5-Mar-20 12:18pm
   
I am not allowed to post full code.
Stefan_Lang 6-Mar-20 3:17am
   
I didn't say post code, I meant that your code doesn't appear to know about your hand-held devices, and the number available! You should put that kind of information in your code, so it doesn't needlessly create new threads.
Member 4099447 6-Mar-20 8:36am
   
Thank you.
I will do

Maybe I'm missing something here, but you're accepting connections. As the number of open connections increases, servicing them takes more CPU time, assuming that messages regularly arrive over them. Indeed, servers need to have an overload control policy that is applied once the CPU becomes fully loaded.
   
v2
That last loop in main() keeps creating new threads as fast as possible. The new threads then get hardly enough time to react, much less exit. As a result you are drowning in an ever-increasing sea of threads, and the CPU spends all of it's time just to manage all those threads, switching context.

You should check the number of active threads and not keep creating new ones unless your active thread count drops below some reasonable limit.
   
Comments
Greg Utas 3-Mar-20 12:03pm
   
I missed that! I just saw the accept() and didn't look further. Goodness, any tutorial that creates a thread per TCP socket knows nothing about building a scalable server.
Stefan_Lang 4-Mar-20 2:35am
   
Well, you *did* say that 'maybe I'm missing something' ;-p

Creating threads unconditionally in a loop can never be a good thing - you don't need to know anything about sockets or servers for that.

*I* don't know anything about that, but I don't think there should be unlimited sockets, nor should any of them be created without a reason (i. e. some kind if client using that socket). I'd expect something like a master thread that receives requests for new connections, and then creates one. Whether in a new thread or not I don't know or care.
Greg Utas 4-Mar-20 7:15am
   
If it's a server, it will create a socket per client. That's OK until it enters overload, at which point it should start to reject TCP connections. But *one* thread can service *all* of the IP port's sockets, listening for connection requests and polling (WSAPoll on Windows) the client sockets for incoming data.
Member 4099447 5-Mar-20 11:04am
   
Number of threads not increase do to the fact that we have only 7 hand held devices that communicate with the server.
When I said in time I mean hours even days.
Maybe because that app runs on s virtual server.I maid an additional thread that one every 10 min checks CPU if over 85 it is restarting app.
My company won't allow to post my code.
Stefan_Lang 6-Mar-20 3:18am
   
The code you posted does not stop at 7, it keeps creating new threads.
Member 4099447 6-Mar-20 8:52am
   
Not true
App starts with 2 threads own and one msvcrt.dll
When I connect 3 clients its growing with 3

https://docs.google.com/spreadsheets/d/e/2PACX-1vT4ovUEMwOehRZmbx5bLrKmh3wCNzP2XX_aas3MMDSTazTH4lLumxa4VlLXqEqmyw/pubhtml

And when I disconnect one its decreasing with 1 as expected.
But I will put a limit just in case.
Stefan_Lang 6-Mar-20 9:29am
   
I think I misinterpreted your code: it's not that it keeps creating too many threads, but it does create too many sockets, and then never closes them.

Compare to the example coded posted here: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept

You can see there that the socket does gets closed even if it's invalid. You don't do that in your code.

Furthermore, you create each socket twice: first within the while condition, and then immediately afterwards within the while block. It overwrites the first socket, without properly releasing it.

So far I don't see why that would create notable CPU load, but I suppose it can't hurt fixing that and see if it helps.
Member 4099447 6-Mar-20 9:38am
   
Here is the running code the main
the thread part receive_cmds(LPVOID lpParam) its too long ,..

`each socket twice:` it was my mistake when posting the code.

Sorry I was afraid to post my real code .I asked my n+ 1 and it is ok


int main()
{
    printf("Starting up multi-threaded TCP server \r\n");
    FILE *fileStream_SQL; char fileText_SQL [240];
    fileStream_SQL = fopen ("PATH_sql.txt", "r");
    fgets (fileText_SQL, 240, fileStream_SQL);
    CONN_STR = fileText_SQL;
    CONN_STR_READ_ONLY =ReplaceString(CONN_STR,"Uid=sa;","Uid=alex_ro;");
    fileText_SQL[0] ='\0';
    fclose(fileStream_SQL);

 // our masterSocket(socket that listens for connections)
 SOCKET sock;

 // for our thread
 //DWORD thread;

 WSADATA wsaData;
 sockaddr_in server;

 // start winsock
 int ret = WSAStartup(0x101,&wsaData); // use highest version of winsock avalible

 if(ret != 0)
 {
	return 0;
 }

 // fill in winsock struct ...
 server.sin_family=AF_INET;
 server.sin_addr.s_addr=INADDR_ANY;
 server.sin_port=htons(23); // listen on telnet port 23

 // create our socket
 sock=socket(AF_INET,SOCK_STREAM,0);

 if(sock == INVALID_SOCKET)
 {
	return 0;
 }

 // bind our socket to a port(port 23)
 if( bind(sock,(sockaddr*)&server,sizeof(server)) !=0 )
 {
	return 0;
 }

 // listen for a connection
 if(listen(sock,5) != 0)
 {
	return 0;
 }

 printf("TCP server sin_port 23 \r\n");

 // socket that we snedzrecv data on
 SOCKET client;

 sockaddr_in from;
 int fromlen = sizeof(from);


 std::thread th_overCPU(overCPU);
th_overCPU.detach();

 // loop forever
  while ((client = accept(sock, (struct sockaddr*)&from,&fromlen))!= INVALID_SOCKET)
    {
    Sleep(250);
    std::thread th_client(receive_cmds,(LPVOID)client);
    th_client.detach();

 }
 // shutdown winsock
 closesocket(sock);
 WSACleanup();

 // exit
 return 0;
}

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900