probleme mit select()

S

Schnabeltasse

Grünschnabel
Hallo zusammen,

ich habe folgendes Problem:
Bin gerade dabei ein "kleines Chatprogramm" zu schreiben.
Dabei handelt es sich um eine Server-Client Applikation.
Das Serverprogramm soll auf Linux laufen und der Client auf Windows.
Nun geht es mir um das Serverprogramm.
Intern arbeitet das Programm mit zwei Threads einen zur Nachrichtenverarbeitung und einen anderen für die Kommunikation übers Netzwerk und den damit verbundenen Verbindungsaufbau über einen Listen Socket.
Die Beiden threads kommunizieren über ein Array von Nachrichten in das der eine schreibt und aus dem der andere liest.

Mein Problem liegt nun im Kommunikationsthread.
nachdem ich select aufgerufen habe mit einem fd_set, in dem auch der ListenSocket drinne ist, ist dieser nicht gesetzt nachdem sich der Client an dem Server angemeldet hat.
Also baut der Client erfolgreich eine Verbindung auf aber merkwürdigerweise kriegt der Server das nicht mit (FD_ISSET gibt keinen erfolg zurück).

Code:
int iListen;
	int iMax = 0;
	int c;
	int iZahl = 0;
	int bytes;
	struct sockaddr_in addr;
	CClientListe* pSender;
	bool bDone = false;
	fd_set fds;
	char buf[1024];

	iListen = socket(AF_INET, SOCK_STREAM, 0);
	if(iListen == -1)
	{
		perror("socket() failed");
	}
	else
	{
		addr.sin_addr.s_addr = INADDR_ANY;
		addr.sin_port = htons(7000);
		addr.sin_family = AF_INET;
		bind(iListen, (struct sockaddr*)&addr, sizeof(addr));
		if(listen(iListen, 3) == -1)
			printf("Fehler bei liste()\n");
		struct timeval timeout;
		while(!bDone)
		{
			FD_ZERO(&fds);
			pthread_mutex_lock(&g_pClients->m_mutex);
				g_pClients->FillSet(&fds);
				iMax = g_pClients->m_iMax;
			pthread_mutex_unlock(&g_pClients->m_mutex);
			FD_SET(iListen,&fds);
			if(iMax < iListen)
				iMax = iListen;
			timeout.tv_sec = 0;
			timeout.tv_usec = 1;
			select(iMax,&fds, NULL,NULL,&timeout);
			if(FD_ISSET(iListen, &fds))
			{
			/// Neuer Client fordert eine Verbindung an ///
				c = accept(iListen,NULL,0);
			//	bytes = read(c,buf,sizeof(buf)); // lies den Benutzername des Clients
				if(bytes != 0)
				{
					printf(buf,"Unbekannter Name");
					pthread_mutex_lock(&g_pClients->m_mutex);
						g_pClients->ClientAdd(buf,c);
					pthread_mutex_unlock(&g_pClients->m_mutex);
				}
				else
					printf("Der Client hat den Namen nich Übergeben");
			}
			else
			{
... verarbeitung wenn der client etwas sendet
Ich hoffe ihr erkennt das Problem, weil ich sitze jetzt schon mehrere Tage daran und habs bisher noch nicht ans laufen gekriegt...:think:

ich danke euch

Jan
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Kleiner Nachtrag von mir.

Also es scheint definitiv an der select(..) Funktion zu liegen.
Da nachdem diese ausgeführt wurde, das übergebene fd_set nicht richtig mit den Werten gefüllt wird.
Kann es sein, dass ich bei Linux noch irgendwelche Einstellungen machen muss, damit select ordentlich läuft? (Firewall hab ich schon ausgestellt)
Ich arbeite mit der openSuse Distr. 10.2
LinuxKernel ist: 2.6.18.2

Hier hab ich mal ne einfachere Version mit nur einem Client(auch der ist reduziert worden auf ein einfaches Windows konsolenprogramm) und ohne Thread,
aber auch die funtzt nicht:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

#define PORT 7000
int main()
{
	int iListen;
	int client = 0;
	int max = 0;
	sockaddr_in addr;
	iListen = socket(PF_INET, SOCK_STREAM,0);
	addr.sin_addr.s_addr = INADDR_ANY;
	addr.sin_port = htons(PORT);
	addr.sin_family = AF_INET;
	if(bind(iListen,(sockaddr*)&addr,sizeof(addr)) == -1)
	{
		perror("bind() failed\n");
		return 2;
	}
	listen(iListen,3);
	

	fd_set fds;
	bool bDone =false;
	char buf[2048];
	int bytes = 0;
	printf("Schleife wird betreten\n");
	while(!bDone)
	{
		FD_ZERO(&fds);
		max = client;
		if(client > 2)
			FD_SET(client,&fds);
		FD_SET(iListen, &fds);
		if(max < iListen)
			max = iListen;
		timeval timeout;
		timeout.tv_sec = 0;
		timeout.tv_usec = 0;
		select(max,&fds,NULL,NULL,&timeout);		
		if(FD_ISSET(iListen,&fds))
		{
			client = accept(iListen,NULL,0);
			printf("neuer client\n");
		}
		if(FD_ISSET(client,&fds))
		{
			bytes = read(client,buf,sizeof(buf));
			if(bytes == 0)
			{
				printf("Client hat Verbindung beendet.\n");
				close(client);
				client = 0;
			}
			else
			{
				if(strcmp(buf,"Shutdown")==0)
				{
					bDone = true;
					printf("Client fährt den Server herunter.\n");
				}	
				else
					printf("Client schreibt: %s",buf);
			}
		}
	}
	close(iListen);
	if(client > 0);	
		close(client);
	return 0;
}
ich hoffe das diese Info euch irgendwie weiterhilft.

Danke schonmal

Jan
 
Zuletzt bearbeitet:
Wenn ich mich recht entsinne muss dein "max" Wert immer größer sein,
als der des höchsten, genutzten Filedeskriptors. Also solltest du max
evtl. noch um 1 erhöhen.

Außerdem prüfst du deine Sockets NUR auf Lesbarkeit.
Wenn du welche auf Beschreibbarkeit prüfen willst, musst du
ein entsprechendes fd_set als drittes Argument bei select()
angeben.

Ich gebe zu,ich habe den Code nur überflogen,
also verzeih mir, wenn ich daneben liege.

Sharoz
 
Nochmals ein Nachtrag:
Ich denke das ich die Lösung gefunden habe:
Nachdem ich select mit dem höchsten Socket +1 mache, dann klappt es soweit.


Jan
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

@Sharoz: hab gerade deinen Beitrag gelesen, danke dir für die Antwort, damit bin ich beruhig, dass das jetzt wirklich der Grund für die Fehlfunktion war.

Jan
 
Zuletzt bearbeitet:

Ähnliche Themen

Unix Webserver mit HTML Seite erstellen

Zugriff Ubuntu 16.04. auf Freigabe 18.04. LTS nicht möglich

Server und Client für TCP und UDP

C HTTP request

Samba 4 Gast Zugang unter Ubuntu funktioniert nicht

Zurück
Oben