PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Socket Programmierung in C/C++


BofD
2005-11-02, 00:21:22
hi,
ich versuche gerade ein einfaches server/client Programm zu schreiben und irgendwie tuts das nicht.
Das Serverprogramm(IP 192.168.1.35) soll auf eine Verbindung warten. Sobald eine Verbindung da ist soll es dann erstmal eine Zahl lesen, die angibt, wie viele weitere Bytes gelesen werden sollen. Hier mal der Quelltext(keine Angst, das meiste ist Debug-Code):
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>

#define MYPORT 3490
#define BACKLOG 10

int main()
{
int sockfd, new_fd;
struct sockaddr_in my_addr, their_addr;
socklen_t sin_size;
int len, bytes_recv;
char* msg[256];


sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
printf("socket(): Konnte keinen Socket erstellen.\n");
return 1;
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = inet_addr("192.168.1.35");
printf("Meine IP: %s\n", inet_ntoa(my_addr.sin_addr));
bzero(&(my_addr.sin_zero), 8);
if(bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1)
{
printf("bind(): Bind fehlgeschlagen.\n");
return 1;
}
if(listen(sockfd, BACKLOG) == -1)
{
printf("linsten(): Listen fehlgeschlagen.\n");
return 1;
}
printf("Warte auf Verbindung ...\n");
sin_size = sizeof(sockaddr_in);
new_fd = accept(sockfd, (struct sockaddr*)&their_addr, &sin_size);
if(new_fd == -1)
{
printf("accept(): Accept fehlgeschlagen.\n");
return 1;
}
printf("%s verbindet ...\n", inet_ntoa(their_addr.sin_addr));
printf("Verbindung steht.\nWarte auf Daten ...\n");
bytes_recv = recv(sockfd, &len, sizeof(len), 0);
if(bytes_recv = -1)
{
printf("read(1): Keine Daten gelesen.\n errno: ");
switch(errno)
{
case EBADF: printf("EBADF: not a valid file descriptor.\n");
case ENOTSOCK: printf("ENOTSOCK: not a socket.\n");
case EWOULDBLOCK: printf("EWOULDBLOCK: nonblocking mode.\n");
case EINTR: printf("EINTR: interrupt befor receive.\n");
case ENOTCONN: printf("ENOTCONN: you never connected this socket.\n");
}
return 1;
}
printf("Incomming header(%d bytes): %d\n", sizeof(len), len);
bytes_recv = recv(sockfd, &msg, len, 0);
if(bytes_recv = -1)
{
printf("read(2): Keine Daten gelesen.\n");
return 1;
}
msg[bytes_recv] = '\0';
printf("Incomming message(%d bytes): %s\n", bytes_recv, *msg);
close(sockfd);
return 0;
}

Der Client macht genau das, was der Server von ihm erwatet:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define DEST_PORT 3490

int main()
{
int sockfd, len;
struct sockaddr_in dest_addr;
char* msg = "hi";
int bytes_sent;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
printf("socket(): Konnte keinen Socket erstellen.\n");
return 1;
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(DEST_PORT);
dest_addr.sin_addr.s_addr = inet_addr("192.168.1.35");
bzero(&(dest_addr.sin_zero), 8);
printf("Server IP: %s\n", inet_ntoa(dest_addr.sin_addr));
if(connect(sockfd, (struct sockaddr*)&dest_addr, sizeof(struct sockaddr_in)) == -1)
{
printf("connect(): Keine Verbindung zum Server moeglich.\n");
return 1;
}
printf("Verbindung zu %s wird aufgebaut...\n", inet_ntoa(dest_addr.sin_addr));
printf("Verbindung steht.\nSende Daten ...\n");
len = strlen(msg);
printf("Sende header(%d bytes): %d\n", sizeof(len), len);
bytes_sent = send(sockfd, &len, sizeof(len), 0);
if(bytes_sent == -1)
{
printf("send(1): Keine Daten gesendet.\n");
return 1;
}
printf("Sende Daten(%d bytes): %s\n", len + 1, msg);
bytes_sent = send(sockfd, msg, len, 0);
if(bytes_sent == -1)
{
printf("send(2): Keine Daten gesendet.\n");
return 1;
}
close(sockfd);
return 0;
}

Als Ausgabe bekomme ich dann:
jojo server # ./server
Meine IP: 192.168.1.35
Warte auf Verbindung ...
192.168.1.35 verbindet ...
Verbindung steht.
Warte auf Daten ...
read(1): Keine Daten gelesen.
errno: ENOTCONN: you never connected this socket.

und
jojo server # ./client
Server IP: 192.168.1.35
Verbindung zu 192.168.1.35 wird aufgebaut...
Verbindung steht.
Sende Daten ...
Sende header(4 bytes): 2
Sende Daten(3 bytes): hi

Wie bekomme ich das zum laufen? Ich bin fuer jede Hilfe dankbar.

Achso: ist natuerlich Linux code, aber zumindest die socket-Functionen sollten die gleichen sein wie bei Win.

Demirug
2005-11-02, 07:26:29
Ja winsock ist fast identisch auch wenn man einiges davon so nicht mehr verwenden soll (wegen IPv6 usw.)

Dein Fehler ist im Server. Dein Serversocket "sockfd" ist ja nur dazu da neue Verbindungen entgegen zu nehmen. Aus diesem Grund erzeugt accept ja auch einen neuen den du zurück bekommst "new_fd". Dein Server Socket "sockfd" wartet dann intern auf die nächste Verbindung. Die Daten die vom Client kommen werden aber "new_fd" zugewiessen. Du musst also "new_fd" zu lesen benutzten. Zudem müsste auch "new_fd" am Ende noch geschlossen werden.

BofD
2005-11-02, 14:35:03
Ok, das klingt logisch. Habs jetzt angepasst (also die beiden recv() Anweisungen + ein close()), aber scheinbar koennen immer noch keine Daten gelesen werden. Der errno code ist aber nun 0. Das komische ist aber, dass der Client scheinbar Daten sendet und das sogar zwei mal ohne einen Error zu bemerken(aber wohin ?).

edit:
Hab gerade festgestellt, dass das Ganze ohne den debug-code funktioniert. Was soll das? recv() gibt zwar -1 zurueck, aber ist trotzdem erfolgreich. Eigentlich bedeutet -1 doch, dass ein Fehler vorliegt, oder hab ich das falsch verstanden?

Demirug
2005-11-02, 14:56:33
Wie wäre es wenn du aus den beiden

if(bytes_recv = -1)

jeweils

if(bytes_recv == -1)

machst?

BofD
2005-11-02, 16:25:34
arr... verdammte Argumente.
Naja dann hat sich das wohl erledigt. Danke fuer die Hilfe!