Thread: multi-threaded listener

  1. #1
    Registered User
    Join Date
    Feb 2006
    Posts
    15

    multi-threaded listener

    Hi everyone
    I've been working on a multi-threaded listener for two weeks now. I've encountered many problem, mainly because I didn't understand thread-enviroment, and windows socket, but I solved almost all of them. But now I have no idea what to do. When in threads, the sockets are in non-blocking mode, so I used "select()" to block until a connection comes, but when I accepted it, it seems that I can't send or recv any data on it. Any communication will fail with "Socket operation on nonsocket." I didn't yet found a solution to this problem.

    Code:
    #include <windows.h>
    #include <iostream.h>
    #include <stdlib.h>
    #include <winsock.h> 
    #include <string.h>
    #include <stdio.h>
    #define MAX_THREADS 2
    #define MAX_MSG_SIZE 100
    #define g 1
    
    DWORD dwTlsIndex; 
    
    bool RUN = 1;
    int th1read = 1;
    void checkversion();
    
    SOCKET go[g];
    SOCKET listener[g];
    SOCKET connected[g];
    
    
    DWORD WINAPI buffoutthread(LPVOID);
    DWORD WINAPI incomingrecive(LPVOID);
    DWORD WINAPI main_function (LPVOID);
    HANDLE hThreads[MAX_THREADS];
    HANDLE main_hThreads[g];
    DWORD  id[MAX_THREADS];
    DWORD  waiter[2];
    HKEY ret,ret1;
    HWND r;
    DWORD exit_code=0x103;
    TCHAR s[255], directory[255];
    BOOL x;
    
    
    LPHOSTENT lpHostEntry, lpHostEntry2;
    unsigned int i;
    unsigned long hostip;
    int port_to_connect=40000;
    int port_number[5]={16567, 29900, 55123, 55124, 55125};
    
    char *msg1="Port to connect: ";
    char *msg2="Ip to connect: ";
    
    char ip_to_connect[64]="83.218.200.230";
    
    
    
    void main(int argc,char **argv){
    
    checkversion();
    	int n[g];
    
    	while(1){
    	for(i=0;i<g;i++){
    
    		n[i] = i;
    		main_hThreads[i] = CreateThread(NULL,0,main_function,&n[i],NULL, NULL);
    		Sleep(300);
    	}
    	
       waiter[2] = WaitForMultipleObjects(g,main_hThreads,TRUE,  INFINITE);
    }
    }
    
    
    
    
    
    DWORD WINAPI main_function (LPVOID k){  
    	AllocConsole();
    	int *p;
    	int port_number;
    	p = (int*)k;
    	fd_set fd_read;
    char buff1[10000];
    int port_to_connect_to_target[5]={16567, 29900, 55123, 55124, 55125};
    	
    
    sockaddr_in clientaddr;
    int iclientaddr = sizeof(clientaddr);
    sockaddr_in comm1;
    comm1.sin_family = AF_INET;
    comm1.sin_port = htons(port_to_connect+*p);   
    	if(hostip!=INADDR_NONE)
    	{
    	comm1.sin_addr.s_addr=hostip;
    			}
    			else
    			{
    				cout << "Can't look up local ip." << endl;
    				WSACleanup();
    				exit(1);
    			}
    	
    //declare target structure
    sockaddr_in target;
    sockaddr_in comm2; 
    comm2.sin_family = AF_INET; 
    comm2.sin_port = htons(port_to_connect_to_target[*p]);
    
    lpHostEntry2 = gethostbyname(hostto); //lpHostEntry2 = gethostbyname();
    if (lpHostEntry2 == NULL) { 
                    cout << "Can't look up remote host." << endl; 
                    WSACleanup(); 
                    exit(1); 
                    }
    comm2.sin_addr = *((LPIN_ADDR)*lpHostEntry2->h_addr_list);
    
    //start of main loop
    while(1){
    
    // start declaration of comm structures
            /* //start of client-server socket 
            if(connected[*p] = socket(AF_INET,SOCK_STREAM,0)){
                         //do nothing
                         }
            else{ //clean up and exit
                 cout << "Can't create client-server socket." << endl; 
                 WSACleanup(); 
                 exit(1); 
    		}  */
            //start of server-target socket
            if(go[*p] = socket(AF_INET,SOCK_DGRAM,0)){
                  //do nothing
                  }
    
            else{ //clean up and exit
                 cout << "Can't create client-server socket." << endl; 
                 WSACleanup(); 
                 exit(1); 
                 }; 
    
    		//declare the socket
    		if((listener[*p] = socket(AF_INET,SOCK_STREAM,0)) == -1) {
    			cout << "listener screwed";
    			cout << WSAGetLastError() << endl;
    		}
    if(bind(listener[*p],(LPSOCKADDR)&comm1,sizeof(comm1)) == -1) {
    			cout << "bind  failed with error ";
    			cout << WSAGetLastError() << endl;
    			exit(1);
    		}
    		
    		//listen for connection
    if((listen(listener[*p],2)) != 0) {
    		cout << WSAGetLastError();
    		exit(1);
    	}  
    
    
            //listen
    		FD_ZERO(&fd_read);
    		FD_SET(listener[*p], &fd_read);
    		cout << WSAGetLastError();
    		if((select(5,&fd_read,NULL,NULL,NULL)) == 0) {
    			cout << "nice";
    			cout << WSAGetLastError() << endl;
    			exit(1);
    		}
    //		printf("%d\n",port_number[i]);
    		if(connected[*p] =  accept(listener[*p],(LPSOCKADDR)&clientaddr,&iclientaddr) == -1){
    			cout << "accept  failed" <<endl;
    			printf("%d\n",WSAGetLastError());
    			exit(1);
    		}
    		FD_ZERO(&fd_read);
    		FD_SET(connected[*p], &fd_read);
    		if((select(5,&fd_read,NULL,NULL,NULL)) == 0) {
    			cout << "nice";
    			cout << WSAGetLastError() << endl;
    			exit(1);
    		}
    		
    		------------------------------------------------------------->DOESN'T WORK
    		if((recv(connected[*p],buff1,sizeof(buff1),0)) < 0){
    			cout << "recv failed" <<endl;
    			printf("%d\n",WSAGetLastError());
    			WSACleanup();
    			exit(1);
    		}
    		printf("%c\n",buff1);
    			;//send(connected[*p],(char*)port_number[*p],sizeof(int),0);
    		//Sleep(3000000);
    		cout << WSAGetLastError();
    if(bind(go[*p],(LPSOCKADDR)&comm2,sizeof(comm2)) == -1) cout << "bind  failed";
    //listen for datagram (use select())
    while(recvfrom(go[*p],buff1,sizeof(buff1),0,(LPSOCKADDR)&target,(int*)sizeof(sockaddr)) != 0){
    	Sleep(900);
    	printf("%d\n",*p);
    }
    printf("%d ggggg\n",*p);
    sendto(go[*p],buff1,sizeof(buff1),0,(LPSOCKADDR)&target,sizeof(target));
    
    //start of comm threads
    hThreads[0] = CreateThread(NULL,0,incomingrecive,(LPVOID)k,NULL,  &id[0]);
    cout <<"............";
    hThreads[1] = CreateThread(NULL,0,buffoutthread,(LPVOID)k,NULL,&id[1]);
    
    
    waiter[1] = WaitForMultipleObjects(MAX_THREADS,hThreads,FALSE,  INFINITE);
    for(int i = 0; i < MAX_THREADS; i++) {
    TerminateThread(hThreads[i],0x103);   //close any rogue threads
    CloseHandle(hThreads[i]);
    }
    
    //close_connection:   
    //end_loop:
    cout << "Socket closed..after threads" << endl;
    closesocket(connected[*p]);
    closesocket(go[*p]);
    goto exit_thread;
    }
    exit_thread:  //exit main thread
    ExitThread(0x103);
    return (DWORD) k;
    }
    
    
    
    
    
    
    //responsible for sending the data to the from peer1 to peer2
    DWORD WINAPI incomingrecive(LPVOID n){
    	int *j;
    	j = (int*)n;
    char incomingbuff[10000];
    
    while(th1read != -1){
    th1read = recv(connected[*j],incomingbuff, sizeof(incomingbuff),0);
    if (th1read == 0) {
       cout << "Socket closed....1" << endl;
       ExitThread(0x103);
       }
    incomingbuff[th1read]='\0';
    send(go[*j],incomingbuff,th1read,0);
    }
    return (DWORD) n;
    }
    
    
    //viceversa
    DWORD WINAPI buffoutthread(LPVOID n){
    	int *j;
    	j = (int*)n;
    
    char buffoutbuff[10000];
    int read = 1;
    while( read != -1 ){
           read = recv(go[*j],buffoutbuff, sizeof(buffoutbuff),0);
           if (read == 0) {
              cout << "Socket closed....2" << endl;
              ExitThread(0x103);
              }
    buffoutbuff[read]='\0';
    send(connected[*j],buffoutbuff,read,0);
    }
    return (DWORD) n;
    }
    
    //check for the right WSA version
    void checkversion() {
    
     WSADATA w; 
    
       if(WSAStartup(0x0202,&w)) 
       { 
          cout << "Can't initialize WinSock." << endl; 
       exit(1);
       } 
             
       if(w.wVersion != 0x0202) 
       {
          cout << "Wrong version." << endl; 
          WSACleanup();
      exit(1);
       } 
    }

  2. #2
    Registered User
    Join Date
    Feb 2006
    Posts
    15
    I can understand how it can be boring to read all those lines of code, so I'll just stick to the basics.
    My question is, How to create a multi-threaded listener? It shoul go like this: start a couple of threads, in each thread runs a listening sockek, on an incoming connection accept the socket?

    I tryed to do this in the obvious way, it doesn't work. Any ideas on how to do this?

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Why, when it's clear you can't even index arrays properly.
    > waiter[2] = WaitForMultipleObjects(g,main_hThreads,TRUE, INFINITE);

    Not to mention code which is
    - poorly indented
    - has poor use of variable names (a global called 'go' for heavens sake)
    - use of unstructured goto

    IMO, you need more practice with the basics of programming first before you make things 1000% more complicated by throwing in threads. Thread programming is pretty tricky stuff for those who do have a clue what they're doing.

  4. #4
    Registered User
    Join Date
    Feb 2006
    Posts
    15
    The present state was achieved, by trying to get around the blocking issue in windows (this led from the use of the socket from a local variable to a global array). This is my first program in windows, and the first time I dealt with windows specifics.

    The original code is a tcp forwarder that works with one connection. The difficulty appeared when I started using threads to forward more than one connection.


    Thanks for you suggestion concerning the basics of programming, but I would appreciate if you would suggest a solution to this problem.
    .

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    How about trying the equivalent of "hello world" using two threads, one to print "hello" and one to print "world", and make it so they always print in the right order.

    > but I would appreciate if you would suggest a solution to this problem.
    Does rewrite it count?

  6. #6
    Registered User
    Join Date
    Feb 2006
    Posts
    15
    I don't mean to sound offensive in two posts you didn't help with any useful information.

    I'm talking about sockets, and how to work with them in a muti-threaded enviroment. Doing an accept() returns a socket that I can't write to.

    About your concern of writing elegant code, the reason I posted this is because I'm trying to solve a problem. When I'll have that solution, then I'll deal with style and the rest. So you see, there's no sense rewriting something that would not work anyway.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Sure, but your code is so f-ugly to look at that no-one, not even you can make any sense of it.

    Coupled with a complete lack of understanding threads in the first place means you have a mess which is simply too much effort to bother with trying to understand and fix.

    > When I'll have that solution, then I'll deal with style and the rest
    Wrong way round - clear code from the outset will help you understand what the hell is going on.
    I mean, if your code was neat, I might bother to actually study it with some effort, but as it stands all I want to do is throw up.

    > So you see, there's no sense rewriting something that would not work anyway.
    I agree, if all you're going to do is rewrite it entirely and then dump it on a message board for debugging and testing.

    > Doing an accept() returns a socket that I can't write to.
    Start there then - write two short programs, one with threads and one without which does an accept call and whatever minimum additional code it takes to make it work. If you get to the point of "this works and that doesn't" then post what you have.

  8. #8
    Registered User
    Join Date
    Feb 2006
    Posts
    15
    Woooo.. no need to get emotional here. I didn't say I'm a C expert
    Thanks for the reply anyway.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Multi dimensional array
    By $l4xklynx in forum C Programming
    Replies: 7
    Last Post: 01-03-2009, 03:56 AM
  2. Help printing a multi array
    By cjohnman in forum C Programming
    Replies: 4
    Last Post: 05-05-2008, 01:35 PM
  3. multi threaded program
    By Dash_Riprock in forum C++ Programming
    Replies: 6
    Last Post: 08-27-2006, 08:38 AM
  4. Replies: 6
    Last Post: 04-26-2004, 10:02 PM
  5. Signals in multi threaded application
    By HelpMe in forum C Programming
    Replies: 0
    Last Post: 09-12-2001, 09:15 PM