Socket UDP Verbindung und mehrere Clients

Gast #4996173
Lesenswert?

Hallo,

eine bestehende C Applikation soll dahingend erweitert werden, dass mit 
eine Applikation mehrere Clients erzeugt und diese jeweils UDP 
Nachrichten versenden und empfangen können.
Die vorhandene C Applikation benutzt einen Thread in dem die ankommenden 
Daten empfangen und weitergereicht werden. Was müsste ich tun, damit ich 
mehrere Client mit einer C Anwendung verwalten kann?
#4996454
Lesenswert?

user schrieb:
> Hallo,
>
> eine bestehende C Applikation soll dahingend erweitert werden, dass mit
> eine Applikation mehrere Clients erzeugt und diese jeweils UDP
> Nachrichten versenden und empfangen können.
> Die vorhandene C Applikation benutzt einen Thread in dem die ankommenden
> Daten empfangen und weitergereicht werden. Was müsste ich tun, damit ich
> mehrere Client mit einer C Anwendung verwalten kann?

Warum nicht ein paar threads pre-create-en (vorher erzeugen) und die 
alle in recvfrom() blockieren lassen. Einer bekommt das datagramm und 
läuft weiter.

Natürlich ist ein bißchen Buchführung notwendig, um immer genug threads 
zu haben ...
Gast #4997007
Lesenswert?

Meine derzeitge Applikation sieht so aus, dass ich für jeden Teilnehmer 
die bind Funktion ausführe und nur einen Thread starte. Im Thread wird 
dann die Funktion recvfrom zum Empfangen von Daten benutzt. Allerdings 
funktioniert dies nicht so wie es sein sollte. Der Empfang funktioniert 
nicht korrekt.
#4997056
Lesenswert?

Rolf M. schrieb:
> Wozu überhaupt select() oder mehrere Threads? Es ist doch UDP. Da kann
> doch doch eh der eine Socket die Daten von allen Clients empfangen, so
> lange sie an den selben Port senden.

Naja, der eine Thread könnte recht lange brauchen, um die Antwort 
zusammen zu stellen, dann kann er nicht wieder zu einem recvfrom() 
zurückkehren.

Und mit select() kann man schauen, ob ein nachflgender syscall 
blockieren würde. Das liefert eine Multiplexlösung ... braucht man bei 
pre-threading nicht.
Gast #4997088
Lesenswert?

Hier wurden nun einige Vorschläge gemacht. Fakt ist das meine Anwendung 
mit nur einem Thread nicht funktioniert. Wie würde das ganze dann mit 
einem Thread und zusätzlich der select Funktion aussehen?
Gast #4997104
Lesenswert?

user schrieb:
> Fakt ist das meine Anwendung
> mit nur einem Thread nicht funktioniert.
Fakt ist, das select bei viele Anwendungen funktioniert - also wird der 
Fehler bei dir legen.

> Wie würde das ganze dann mit
> einem Thread und zusätzlich der select Funktion aussehen?
mal schnell etwas mit Threads machen, ist eine sehr schlechte Idee. Da 
muss man sich schon ein paar Gedanken über Synchronisation und 
Kommunikation der Threads machen.

Dafür müsste aber wissen was genau das Programm machen soll.
Gast #4997274
Lesenswert?

Für das Empfangen von UDP Nachrichten wird ein Thread benutzt.
Die Empfangsfunktion kann dann außerhalb von diesem Object aufgerufen 
werden.
1
objectUDP*  UDPPort[MAXUDPPORTS];
2
HANDLE      hUdpThread;
3

4
DWORD WINAPI UDPThread(LPVOID lpParameter)
5
{
6
  int i;
7
  fd_set    read_handles;
8
  struct    timeval timeout_interval;
9
  int       retval;
10
  int       max_server_handle = 0;
11

12
  while(1)
13
  {
14
    FD_ZERO(&read_handles);
15
    for (i = 0; i < MAXUDPPORTS; i++)
16
    {
17
      if (UDPPort[i])
18
      {
19
        FD_SET(UDPPort[i]->Socket, &read_handles);
20
      }
21
    }
22

23
    timeout_interval.tv_sec = 1;
24
    timeout_interval.tv_usec = 0;
25

26
    retval = select(max_server_handle + 1, &read_handles, NULL, NULL, &timeout_interval);
27
    if (retval == -1)
28
    {
29
      printf("Select error\n");
30
      //error
31
    }
32
    else if (retval == 0)
33
    {
34
      printf("timeout\n");
35
    }
36
    else
37
    {
38
      //good
39
      for (i = 0; i < MAXUDPPORTS; i++)
40
      {
41
        if (UDPPort[i])
42
        {
43
          if (FD_ISSET(UDPPort[i]->Socket, &read_handles))
44
          {
45
            if (UDPPort[i]->m_ReceiveBufferLen == 0)
46
            {
47
              int rcvlen = sizeof(sockaddr_in);
48
              int Len;
49
              if ((Len = recvfrom(UDPPort[i]->Socket, UDPPort[i]->m_ReceiveBuffer, UDPBufferLen, 0, (sockaddr*)&UDPPort[i]->m_ReceiveAddr, &rcvlen)) < 0)
50
              {
51
                perror("Error in recvfrom.");
52
                break;
53
              }
54

55
              printf("\nData received on socket %d:", i);
56

57
              UDPPort[i]->m_ReceiveBufferLen = Len;
58
              if (UDPPort[i]->m_InterruptControl) UDPPort[i]->pM->Operate(UDPPort[i]);
59
            }
60
          }
61
        }
62
      }
63
    }
64
  }
65
  return 0;
66
}
67

68
int objectUDPPort_Receive(objectUDP* pInst, char* pMsg)
69
{
70
  int Len;
71

72
  Len=pInst->m_ReceiveBufferLen;
73
  if (Len)
74
  {
75
    int CountMax=Len;
76
    int  i;
77

78
    if (MaxLen<Len) CountMax=MaxLen;
79
    for (i=0;i<CountMax;i++) pMsg[i]=pInst->m_ReceiveBuffer[i];
80
    pInst->m_ReceiveBufferLen=0;
81
  }
82
   return Len;
83
}
84

85
objectUDPPort   *UPort[2];
86

87
void main(void)
88
{
89

90
  UPort[0] = (objectUDPPort *)malloc(sizeof(objectUDPPort));
91
  UPort[1] = (objectUDPPort *)malloc(sizeof(objectUDPPort));
92

93
  _objectUDPPort(UPort[0], "192.168.0.1", 1000, 1001); // UDP-Client
94
  _objectUDPPort(UPort[1], "192.168.0.2", 1000, 1002); // UDP-Client
95
  
96
    while(1)
97
    {
98
     int Len;
99
    char Buffer[100];
100
    Len = UPort[0]->pM->Receive(UPort[0], Buffer, 512, 0);
101
    if (Len)
102
    {
103
    
104
    }
105
    }
106
}
Gast #4997325
Lesenswert?

user schrieb:
> Für das Empfangen von UDP Nachrichten wird ein Thread benutzt.
> Die Empfangsfunktion kann dann außerhalb von diesem Object aufgerufen
> werden.

kannst du jetzt noch mal genau schreiben, was passiert bzw. wo das 
Problem liegt.

Du hattest ja geschrieben, das select blockiert, aber du hast du einen 
timeout von 1 sekunde - länger dürfte es nicht blockieren.
Gast #4997353
Lesenswert?

Konstruktor:
1
void _objectUDPPort(objectUDPPort* pInst, char* ToIPAddr, int DstPort, int SrcPort)
2
{
3
  pInst->pM->Destroy              = (void(*)(void*))*objectUDPPort_Destroy;
4
  pInst->pM->Send                = (void(*)(void*,char*,int,int))*objectUDPPort_Send;
5
  pInst->pM->Receive              = (int (*)(void*,char*,int,int))*objectUDPPort_Receive;
6

7
    pInst->m_ReceiveBufferLen=0;
8
  pInst->m_PortIndex = 0;
9

10
  unsigned long Identifyer;
11
  hndUdpThread = CreateThread(NULL, 0, UDPThread, (LPVOID)0, 0, &Identifyer);
12

13
  // Socket DLL oeffnen
14
  WSADATA wsaData;
15
  if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData )!=0 )
16
    MessageBox(0,(LPCWSTR)"UDP",(LPCWSTR)"WSA Socket DLL not found!",MB_OK);
17

18
  // Index fuer globle Objektdaten suchen
19
  while (UDPPort[pInst->m_PortIndex] && pInst->m_PortIndex<2) pInst->m_PortIndex++;
20
  if (pInst->m_PortIndex == 2)
21
  { // Keine freie Hardwarerecource
22
    pInst->m_PortIndex = -1;
23
    return;
24
  }
25

26
  // Client Configuration
27
  pInst->m_SendAddr.sin_family=AF_INET;
28
  pInst->m_SendAddr.sin_addr.S_un.S_addr=inet_addr(ToIPAddr);
29
  pInst->m_SendAddr.sin_port=htons(DstPort);
30

31
  pInst->m_ReceiveAddr.sin_addr.S_un.S_addr=0;
32

33
  // Socket oeffnen
34
  pInst->Socket = socket(AF_INET, SOCK_DGRAM, 0);
35

36
  if (pInst->Socket != INVALID_SOCKET)
37
  {
38
    sockaddr_in name;
39
    name.sin_family = AF_INET;
40
    name.sin_port = htons(SrcPort);
41
    name.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
42
    if (bind(pInst->Socket, (sockaddr*)&name, sizeof(name)) == SOCKET_ERROR)
43
    {
44
      closesocket(pInst->Socket);
45
      pInst->Socket = INVALID_SOCKET;
46
    }
47
    else
48
    {
49
      int result = 0;
50
      int Timeout_ms = 1;
51

52
      if (result == SOCKET_ERROR)
53
      {
54
        closesocket(pInst->Socket);
55
        pInst->Socket = INVALID_SOCKET;
56
      }
57
      else
58
      {
59
        UDPPort[pInst->m_PortIndex] = pInst;
60
      }
61
    }
62
  }
63
  else
64
  {
65
    int Err = WSAGetLastError();
66
  }
67
}
(Firma: Schweigstill IT) Persönliche Seite #4997578
Lesenswert?

user schrieb:
> Ich hab im Netz recherchiert.

Aha. Stammen die obigen Quellcodeabschnitte denn auch "aus dem Netz"?

Unter welchen Lizenzbedingungen darfst Du sie denn verwenden? Bei den 
meisten Open-Source-Lizenzen werden doch die Nennung des Urhebers und 
der Lizenzbedingungen selbst verlangt.

Oder hast Du etwa eine juristisch durchaus relevante 
Urheberrechtsverletzung begangen?
(Firma: Schweigstill IT) Persönliche Seite #4997583
Lesenswert?

Der Andere schrieb:
> Auf Deutsch: solange irgendwelche Codeschnipsel aus dem Netz
> zusammengebastelt bis es anscheinend funktioniert.

Solch einen Typen hatte ich auch einmal eingestellt, der völlig wahlfrei 
irgendwelche Codeschnipsel aneinanderreihte und dem noch nicht einmal 
bewusst war, dass man diese Teile zumindest über Funktionsaufrufe, 
Datenstrukturen o.ä. miteinander verbinden musste. Und derjenige war 
sogar Diplom-Informatiker, frisch von der FH! Kurze Zeit später war er 
wieder arbeitslos, fand aber schnell einen weiteren Job, aus dem er 
sogar noch schneller wieder hochkant herausflog. Der Typ hatte wirklich 
keinerlei Vorstellungen davon, was er überhaupt falsch machte.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren