Jump to content

  • Log In with Google      Sign In   
  • Create Account


Megahertz

Member Since 19 Oct 2000
Offline Last Active Jan 16 2014 11:29 PM

Topics I've Started

epoll troubles [Solved]

31 December 2007 - 01:16 PM

Ugh. I hate having to post my code on here to get help with whats going on, but I've just not been able to find the problem.

Basically heres whats going on. I've written a few hundred line epoll server (Fedora Core 4) that listens for connections, accepts them, and continues to recieve data on them until i shut down the client.

The client program (Windows XP) does nothing more than create a given number of clients, connects them to the server and at a given interval (5 times a second atm) sends a 512 byte packet to the server.

When I first start up the server and start up the client program everything is fine. Everything connnects, no errors on either side and the clients merrily start sending their packets to the server. However at some random time usally about 20-30 seconds after the client starts sending packets the last 1-5 (so far) clients in the list start blocking on their send calls. At first I was using non-blocking sockets on the sending side, hey if a socket blocks for a few ms, no biggie. Problem is that it would block almost indefintley. After getting this problem I switched to non-blocking sockets for the client. As expected I now get WSAEWOULDBLOCK errors where previously I blocked. Ok, thats fine, however now with the non-blocking code I get inconsistencies with which of those last 1-5 sockets actually give a WSAEWOULDBLOCK error. Ok thats sorta fine too, except it contradicts the previous behavior of when a socket would block, it would stay blocked. I've got no idea what its waiting on....for so long!?

Ok heres the kicker, I changed out the CTestServer::Run() method (will be posted below) of the server and converted just that method over to use select rather than epoll and I have absolutely no issues with the sockets. No blocking, I got a shower, went and got food and came back and it was still purring along.

In any event, heres the code for the meat of the server, I can post more should there be a request, but if theres a problem. I'll bet its here.

Thanks in advance for any help.

-=[ Megahertz ]=-

int CTestServer::Run()
{
	
	// Create our epoll file descriptor
    const int max_events = 1024;
    int epoll_fd = epoll_create(max_events);
    if (epoll_fd == -1) {
		printf("epoll_create\n");
		return 0;
    }
    
    // Add our server fd to the epoll event loop
    struct epoll_event event;
    event.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLET;
    event.data.fd = listener->GetSocket();
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listener->GetSocket(), &event) == -1) {
		printf("epoll_ctl\n");
		return 0;
    }
    int conncount=0; 
   	printf("Waiting....\n");

	struct epoll_event events[max_events];
    // Execute the epoll event loop
    while (true) {

		
		//wait for something to happen
		int num_fds = epoll_wait(epoll_fd, events, max_events, -1);
		
		
		// loop through all the fds that had activity
		for (int i = 0; i < num_fds; i++) {
			
		    // Case 1: Error condition
		    if (events[i].events & (EPOLLHUP | EPOLLERR)) {
				printf("epoll: EPOLLERR");
				close(events[i].data.fd);
				return 0; //just a test to see if it should bail out.
				//continue;
		    }
		    assert(events[i].events & EPOLLIN);

		    // Case 2: Our server is receiving a connection
		    if (events[i].data.fd == listener->GetSocket()) {
				struct sockaddr remote_addr;
				socklen_t addr_size = sizeof(remote_addr);
				int connection = accept(listener->GetSocket(), &remote_addr, &addr_size);
				if (connection == -1) {
				    if (errno != EAGAIN && errno != EWOULDBLOCK) {
						printf("accept error\n");
					}
					return 0;
				}	
					
				// Add the connection to our epoll loop
				event.data.fd = connection;
				if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, connection, &event) == -1) {
				    printf("epoll_ctl\n");
				    return 0;
				}
				printf("New Connection! %d\n",conncount++);
				continue;
		    }
	    


		    // Case 3: One of our existing connections has read data 
	
			char buf[5120];
			memset(buf,0,5120);
			int bytes = recv(events[i].data.fd,&buf,5120,0);
			if (bytes<=0) { //so far unless i terminate the clients, this never happens (which is good)
				close(events[i].data.fd);
				printf("Closed connection: %d\n",events[i].data.fd);
			}
			else {
				printf(" %d Bytes from client %d\n",bytes,events[i].data.fd);			
			}		
		}
	}	
}	





[Edited by - Megahertz on January 1, 2008 12:10:59 AM]

GameDev.net Site Performance

19 October 2006 - 10:36 AM

Is it just me or does gamedev.net seem horribly slow to navigate? It's taking upwards of 7 seconds to open a page (mainly I just browse the forums) I don't recall things being this slow, say, 6mo. to a year ago. I'm wanting to say its the ads because most of the background page loads, then it loads an ad and I see down in the status bar its sitting there waiting on a response from whatever server the ad is hosted from. Once the ad stuff is done the rest of the page shows up. Anybody else getting this too? -=[ Megahertz ]=- P.S. I'm using Firefox 1.5.0.7 on Windows XP

Routing packets to the right client.

12 December 2005 - 06:58 PM

I've recently tried using epoll on linux as a way of event notification on sockets. epoll_wait() works pretty much like select does. You give it a list of file descriptors and when something happens if falls through with a list of which ones had activity. My problem is that when something happens on a FD, I have no idea which client the socket belongs to. Should I keep a mapping of FD's to clients? That seems rather klunky and I'd like to avoid iterating through a list to find out which client should get the data. Suggestions? -=[ Megahertz ]=-

Single Threaded UDP

23 July 2005 - 05:21 PM

Currently my servers for my small MMO project have been written using multiple threads. I'm considering rewriting the network portion of it so that it all operates inside a single thread (The databse stuff will still have to be threaded so that queries can be done asynchronosly). Right now the loop that recieves data off the listening socket runs in it's own thread. It sits on a select call until data shows up and once it does the select call falls through and the incomming data is processed and the packets are put on the respective clients incomming queue where it'll be pulled off and dealt with by the main thread. Does moving this stuff to the main thread mean that I'll no longer be using select to block on the socket and instead just call recvfrom to see if there's data? I'm guessing that I just keep looping calling recvfrom until I get to a point where I get no data from the socket, then just fall through and run the logic for the server. Ideally, I'd like to do all this in a manner so that it doesnt hog up the CPU because the server is just running in a infinite busy loop. Ideas? -=[ Megahertz ]=-

Geomipmapping and Triangle Strips

15 May 2005 - 12:58 PM

I'm looking into doing an implementation of geomeipmapping and i've been working out the details. I've read Willem H. de Boer's paper and understand the theory behind it, but I've still got a few questions. My biggest question is given a patch with any LOD and any configuration of neighboring LOD's is it possible to render the patch with a single draw call using triangle strips as the primitive. Or do you have to resort to using fans or some other primitive for the edges. I've done up some images in trying to work this out. This is the base patch. Can be drawn using 1 call (each row linked with degenerates) Image 1 This is with the top row going down 1 LOD level to match the patch above it. I'm pretty sure this can be done with a single draw call. Image 2 This is with the left and top edges knocked down one LOD level however, I'm not sure this can be done with one call. Image 3 Beyond this, im not sure. Any insight on this would be appreciated. -=[ Megahertz ]=-

PARTNERS