Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. Cast down
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    321
    Rep Power
    11

    winsock, a few questions, getting client addr/sending data


    I am writing a simple winsock app. It listens for connections and just echo's whatever the client types, how would I get the client's IP?

    also if I were to make a chat program, how would I send data back to the client, I know you use send() and I know how to use it, but if you look at my code. WHERE do I have time to allow server to input data and send it?

    Code:
    #include <windows.h> 
    #include <winsock.h> 
    #include <stdio.h> 
    
    int main()
    {
    	WORD sckVersion; 
    	WSADATA wsaData; 
    	SOCKET sckListen; 
    	SOCKET sckClient; 
    	SOCKADDR_IN servN; 
    	SOCKADDR_IN clientN; 
    	int ret; 
    	char buffer[] = "Hello"; 
    	char rbuff[50]; 
    
    	sckVersion = MAKEWORD(1,1); 
    	WSAStartup(sckVersion,&wsaData); 
    
    	//Set up listening socket 
    	sckListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    	if(sckListen==INVALID_SOCKET)
    	{
    		printf("****ing error @ sckListen\n"); 
    		return 0; 
    	}
    
    	//fill serv info 
    	servN.sin_family = AF_INET; 
    	servN.sin_addr.s_addr = INADDR_ANY; 
    	servN.sin_port = htons(1016); 
    
    	//bind 
    	if(bind(sckListen,(LPSOCKADDR)&servN,sizeof(struct sockaddr))==SOCKET_ERROR)
    	{
    		puts("Error @ bind"); 
    		return 0; 
    	}
    
    	puts("Listening on port 1016"); 
    	do
    	{
    		if(listen(sckListen,SOMAXCONN)==SOCKET_ERROR)
    		{
    			puts("error at listen"); 
    			return 0; 
    		}
    		//when someone connects 
    		sckClient = accept(sckListen,(LPSOCKADDR)&clientN,NULL); 
    		if(sckClient==INVALID_SOCKET)
    		{
    			puts("****ed @ accept"); 
    			return 0; 
    		}
    
    		puts("someone connected!"); 
    		//send(sckClient,buffer,sizeof(buffer),MSG_OOB); 
    		do
    		{
    			for(ret=0;ret<50;ret++)
    			rbuff[ret]='\0';  
    
    			if(recv(sckClient,rbuff,sizeof(rbuff),0)==0) 
    			{
    				puts("Client disconnected!"); 
    				break; 
    			}
    			printf("Client: %s\n",rbuff); 
    		}while(1); 
    	} while(1); 
    	return 0; 
    }
  2. #2
  3. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    you could do...
    Code:
     printf("incoming connection from address %s\n", ( inet_ntop(AF_INET, &clientN.sin_addr.s_addr, name_buffer, ADDR_LEN) );
    where name_buffer is a char* to a buffer for ascii dotted decimal address and ADDR_LEN is the maximum length of an IP address including NULL terminator, or 16.
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    In other words, in case you hadn't caught it, the client's address, both IP and port number, is returned in the clientN parameter by the accept call:
    Code:
    sckClient = accept(sckListen,(LPSOCKADDR)&clientN,NULL);
  6. #4
  7. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    also to zero out your buffer, it would easier to just go
    Code:
    bzero(rbuf, sizeof(rbuf));
    if your making a chat program, i would consider using UDP instead and implementing a simple acknowledgment scheme. but in your example above, do you want a server to be a broadcast server? where it would broadcast all the messages it recieves to all the clients? i constructed a win32 chat program that uses TCP with the broadcasting scheme. each client spawned a separate thread that listened for messages from that client and then broadcasted that message to all the clients. all the addresses were stored in a global structure. if you'd like to see the source let me know.
  8. #5
  9. Cast down
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    321
    Rep Power
    11
    I knew that clientN was holding the addr and port, but I didn't know how to convert them to a presentable format (char array), What do I need to include to use inet_ntop?
  10. #6
  11. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>

    on windows should just be
    #include <winsock2.h>

    i think
  12. #7
  13. Cast down
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    321
    Rep Power
    11
    hm, program works if I link ws2_32.lib, and only include windows.h. But if I include winsock2, it gives me a lot of redifinition errors. Still can't get inet_ntop();

    Ok, including winsock2 behind windows.h fixed THAT, but I get Socket1 error LNK2019: unresolved external symbol _inet_ntop referenced in function _main
    Last edited by movEAX_444; August 18th, 2003 at 08:20 PM.
  14. #8
  15. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    hmm i donno i always hated those damn link errors they're so annoying! you have all your stuff syntactically correct and you just WANT TO SEE IF IT DAMN WORKS and those miserable link errors, argh! sorry i have nothing constructive to add ;)
  16. #9
  17. It Doesn't Work!
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Location
    Slovenia
    Posts
    112
    Rep Power
    11
    I think for a chatroom you'd need non-blocking (asynchronous) sockets...
  18. #10
  19. Cast down
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    321
    Rep Power
    11
    Alright, I will use non-blocking, but for now my only mission in life is to printf the client's ip. @ madwizard.org's winsock tutorial, he does this:

    Code:
    string GetHostDescription(const sockaddr_in &sockAddr)
    {
        ostringstream stream;
        stream << inet_ntoa(sockAddr.sin_addr) << ":" << ntohs(sockAddr.sin_port);
        return stream.str();
    }
    When I do printf("%s\n",inet_ntoa(sckClient.sin_addr)); I get "204.204.204.204" no matter who connects, if it's localhost or someone remotely.
  20. #11
  21. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Originally posted by movEAX_444
    When I do printf("%s\n",inet_ntoa(sckClient.sin_addr)); I get "204.204.204.204" no matter who connects, if it's localhost or someone remotely.
    The syntax most certainly looks correct and it matches what I have done in my programs.

    Are you sure that sckClient is getting loaded correctly? You might want to try a sanity check by also printing out the IP address as a 32-bit unsigned; e.g.:
    Code:
    printf("%s [%08X]\n",inet_ntoa(sckClient.sin_addr),sckClient.sin_addr);
    if you get a string of 204.204.204.204 [CCCCCCCC], then the fault lies with the value being loaded into sckClient.sin_addr and not with inet_ntoa().
  22. #12
  23. Cast down
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    321
    Rep Power
    11
    Thanks. It was a problem @ accept(); I had to put the last param.

    ret = sizeof(struct sockaddr);
    sckClient = accept(sckListen,(LPSOCKADDR)&clientN,&ret);
  24. #13
  25. Cast down
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    321
    Rep Power
    11
    Ok, now I have it spawn a new thread for every client that connects, and the client can send msg's to the server, but how do I make the server broadcast a msg to all the clients?
  26. #14
  27. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Originally posted by movEAX_444
    Ok, now I have it spawn a new thread for every client that connects, and the client can send msg's to the server, but how do I make the server broadcast a msg to all the clients?
    I believe that Infamous has more actual experience with this, but I would think that since you have a list of all the clients you could simply iterate through that list and have each client's thread send it a copy of that message. Similar, I'm sure, to how the Linux processes the wall command, which sends the same message to all the users logged onto the system.
  28. #15
  29. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    here is my code from my program.
    Code:
    // (c) Broadcast message to all of the clients logged in
    		for(int y = 0; y < num_clients;y++)
    		{
    			nBytesSent = send(client_list[y],(char *) &outgoing_data, 
    				sizeof(outgoing_data),NO_FLAGS_SET);
    			
    			if ((nBytesSent == 0) || (nBytesSent == SOCKET_ERROR))
    			{
    				if(nBytesSent == 0){ printf("Gracefully shutting down...\n");}
    				else
    				{
    					EnterCriticalSection(&critSec);
    					printf("send: Thread %u Failed with error #%u\n", myID, WSAGetLastError());
    					LeaveCriticalSection(&critSec);	
    				}	
    				exit = true;
    				break;
    			}
    		}
    note: i wrote this 6 months ago when i first learned sockets, so i take no responsibility for errors :D
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo