select...

2fast4you87

Erfahrenes Mitglied
Hallo Leute,

ich steh grad ein wenig auf dem Schlauch. Habe mit Visual C++ vs. 6.0 einen TCP Server programmiert der die angenommen Sockets in eine Liste speichert! Mit recv hört und die Daten ausgibt, dass das ganze nicht blockiert select hinzugefügt. Mein problem ist aber das er zwar die clients annimmt aber :


- Die Nachrichten erst ausgibt wenn z.B Client 1 was schreibt sprich :
Connect : C1 und C2 => C2 schreibt was wird nicht ausgegeben bis C1 was schreibt.
- Der Server gibt nicht aus, wenn ein Client Disconnectet-
- Der Server gibt nur immer die erste Nachricht aus.

Hier mal der Code :

Code:
server.cpp

int main(int argv,char *argc[])
{
	SOCKET sCs;
	timeval Timeout;
	Timeout.tv_sec = 0;
	Timeout.tv_usec	= 0;
	FD_SET fdSet;
	long lRc = 0;
	char buf[256];

	SList * serv = SList::new_instanz((u_short)12345); // Singleton class
	serv->start_serv(); // starte server mit port 12345

	for(;;) //endlos
	{
		FD_ZERO(&fdSet); //deskrptor leeren
		FD_SET(serv->get_sS(),&fdSet); // setze socket von class

		if((lRc = select(0,&fdSet,NULL,NULL,&Timeout)) == SOCKET_ERROR)
			cout << " Error : Select . \n"; //select error
		
		if(FD_ISSET(serv->get_sS(),&fdSet)) // wenn socket hinzugefügt
		{
			if((sCs = accept(serv->get_sS(),NULL,NULL)) != INVALID_SOCKET)
			{
				cout << "Neue Verbindung wurde angenommen !\n"; // neuer client angenommen
				serv->push_back(sCs); // in die liste rein
				FD_SET(sCs,&fdSet); // setze neuen client
			}
		}

		for(int i = 0;i < (int)serv->size;++i) //laufe liste durch
// size is public, hab ich auf die schnelle so gemacht :( ^^
		{
			if(FD_ISSET(serv->get_cCs(i),&fdSet)) // wenn client da
			{
				lRc = recv(serv->get_cCs(i),buf,sizeof(buf),0); 
// hören ob nachricht kommt
				if(lRc != 0 || lRc != SOCKET_ERROR)
				{ // keine fehler
					buf[lRc] = '\0'; // terminieren
					cout << buf << endl;  // ausgabe
					break;
				}
				else
				{
					cout << "Verbindungsfehler ... \n";
					break; // fehler 
				}
			}
		}
	}



	WSACleanup(); //aufräumen
	return 0;
}

Slist.cpp (Liste mit der methode push_back() und start_serv())


//-------------------------------------
void SList::start_serv()
{
	if((lRc = startWinsock()) == 0)
		cout << "Winsock gestartet!\n";
	else
		cout << "Error : Winsock .\n";
	if((sS = socket(AF_INET,SOCK_STREAM,0)) != INVALID_SOCKET)
		cout << "Socket wurde erstellt!\n";
	else
		cout << "Error : Socket .\n";

	//...
	memset(&addr,0,sizeof(SOCKADDR_IN));
	addr.sin_family			= AF_INET;
	addr.sin_port			= htons(usPort);
	addr.sin_addr.s_addr	= INADDR_ANY;
	//...

	if((lRc = bind(sS,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN))) != SOCKET_ERROR)
		cout << "Socket wurde an Port " << usPort << " gebunden!\n";	
	else
		cout << "Error : Bind .\n";
	if((lRc = listen(sS,10)) != SOCKET_ERROR)
		cout << "Listen modus ...\n";
	else
		cout << "Error : Listen .\n";
}

//-------------------------------------
void SList::push_back(SOCKET _sVal)
{
	_knoten * tmp = new _knoten;
	tmp->next = 0;
	tmp->sC = _sVal;

	if(_anfang == 0)
	{
		_anfang = tmp;
		_ende = tmp;
		++size;
	}
	else
	{
		_knoten * _tmp = _ende;
		_tmp->next = tmp;
		_ende = tmp;
		++size;
	}
}

Könnt ihr mit da weiterhelfen?

Gruß 2fast ...
 
Hi...

ich denke ein Problem ist dein selet Aufruf ansich

Code:
// dein select
select(0,&fdSet,NULL,NULL,&Timeout)

Du solltest dir mal die Doku zum select Aufruf ansehen, da steht nämlich folgendes:
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

n is the highest-numbered descriptor in any of the three sets, plus 1.

Du übergibst als n aber 0 und meines Wissens nach ist das STDIN, das kann also nicht funktionieren (ist so auf UNIX und Linux, ich kann dir nicht sagen, wie es auf Windows aussieht, müsste doch aber gleich sein oder?).

Du müsstest als n also mindestens den Wert von deinem socket filedeskriptor + 1 übergeben.

HTH

Sebastian
 
ne, unter windows ist das mein ich anders, aber auch mit der +1 tut das nicht, habe mich an dem Tutorial von C-Worker.ch orrientiert da tut das!
...
 
hier nochmal der Auszug vom dem windows select:


int select (
int nfds,
fd_set FAR * readfds,
fd_set FAR * writefds,
fd_set FAR * exceptfds,
const struct timeval FAR * timeout
);

Parameters
nfds in This parameter is ignored; it is included only for compatibility with Berkeley sockets.
 
Hallo,

So Habe den Fehler gefunden.
Code:
//-------------------------------------
void SList::start_hear()
{
	Timeout.tv_sec = 0;
	Timeout.tv_usec	= 0;

		for(;;)
		{
			FD_ZERO(&fdSet);
			FD_SET(sS,&fdSet);

			for(int z = 0;z < (int)size;++z)
			{
				FD_SET(get_cCs(z),&fdSet); 
//hier war der Fehler ich darf nicht sofort nach Accept den Socket in das FD_SET Array 
//schreiben
			}

			if((lRc = select(0,&fdSet,NULL,NULL,&Timeout)) == SOCKET_ERROR)
				cout << " Error : Select . \n";
				
			if(FD_ISSET(sS,&fdSet))
			{
				if((sCs = accept(sS,NULL,NULL)) != INVALID_SOCKET)
				{
					cout << "Neue Verbindung wurde angenommen !\n";
					push_back(sCs);
				}
			}


			for(int i = 0;i < (int)size;++i)
			{
				if(FD_ISSET(get_cCs(i),&fdSet))
				{
					lRc = recv(get_cCs(i),buf,sizeof(buf),0);
					if(lRc == 0 || lRc == SOCKET_ERROR)
					{
						cout << "Client ["<< i  <<"] Disconnect ...\n";
						closesocket(get_cCs(i));
						del_itm(i);
// Und ich sollte schon die Clients aus der Liste wieder entfernen und
// den Socket schließen ;-)
					}
					else
					{
						buf[lRc] = '\0';
						cout << buf << endl;
					}
				}
			}
		}
}

Gruß 2fast...
 
Zurück