Serwer tcp w C sie wywala po odłaczeniu klienta

0

Napisałem taki o to serwerek

	#include <stdio.h>
	#include <string.h>
	#include <stdlib.h>
	#include <unistd.h>
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>
	#include <sys/select.h>

	void DrukujNadawce(struct sockaddr_in *adres)
	{
	printf("Wiadomosc od %s:%d",
	inet_ntoa(adres->sin_addr),
	ntohs(adres->sin_port)
	);  
	}

	int ObsluzTCP(int gniazdo, struct sockaddr_in *adres)
	{
	int nowe_gniazdo;
	char bufor[1024];
	socklen_t dladr = sizeof(struct sockaddr_in);
	nowe_gniazdo = 
	accept(gniazdo, (struct sockaddr*) adres, 
	  &dladr);
	if (nowe_gniazdo < 0)
	{
	printf("Bledne polaczenie (accept < 0)\n");
	return;
	}


	return nowe_gniazdo;

	}
	int KakaTCP(int gniazdo, int tablica[], int i,struct sockaddr_in *adres)
	{
	int p;
	char bufor[1024];
	socklen_t dladr = sizeof(struct sockaddr_in);
	memset(bufor, 0, 1024);
	if (recv(gniazdo, bufor, 1024, 0) >= 0){
	DrukujNadawce(adres);
	printf("[TCP]: %s\n", bufor);
	p=0;
	while (p<=i){

	send(tablica[p], bufor, 1024, 0); 

	p=p+1; 
	}}

	}


	void ObsluzObaProtokoly(int gniazdoTCP,
						struct sockaddr_in *adres)
	{
	fd_set readfds;
	struct timeval timeout;
	int proba;
	int maxgniazdo, i,j=0;
	int gniazdka[10];


	maxgniazdo = gniazdoTCP+1;
	i = -1;
	proba = 0;


	while(1)
	{
	  j=0;
	FD_ZERO(&readfds);
	FD_SET(gniazdoTCP, &readfds);
	while(j<=i){
	FD_SET(gniazdka[j], &readfds);
	j=j+1;}
	timeout.tv_sec = 1;
	timeout.tv_usec = 0;
	if (select(maxgniazdo, &readfds, NULL, NULL, &timeout) > 0)
	{
	  proba = 0;
	  if (FD_ISSET(gniazdoTCP, &readfds)){
		  i=i+1;
	gniazdka[i]=ObsluzTCP(gniazdoTCP, adres);


	maxgniazdo=gniazdka[i]+1;


	}

	while(proba<=i){
	  if (FD_ISSET(gniazdka[proba], &readfds)){
	KakaTCP(gniazdka[proba], gniazdka, (i),adres);}
	printf("proba = %d", proba);
	proba=proba+1;}
	}
		}


	}
	int main(void)
	{
	struct sockaddr_in bind_me_here;
	int gt, port;

	printf("Numer portu: ");
	scanf("%d", &port);

	gt = socket(PF_INET, SOCK_STREAM, 0);

	bind_me_here.sin_family = AF_INET;
	bind_me_here.sin_port = htons(port);
	bind_me_here.sin_addr.s_addr = INADDR_ANY;

	if (bind(gt,(struct sockaddr*) &bind_me_here,
		   sizeof(struct sockaddr_in)) < 0)
	{
	printf("Bind na TCP nie powiodl sie.\n");
	return 1;
	}



	listen(gt, 10);

	ObsluzObaProtokoly(gt, &bind_me_here);

	return 0;
	}

po odłaczeniu klienta serwer konczy prace... zanim sie wyłaczy pisze ze otrzymuje jakies puste wiadomosci...

0

poczytaj o sigpipe:

  1. signal(SIGPIPE,SIG_IGN)

  2. recv i send obsluguja flage MSG_NOSIGNAL pod linuksem, ale dla bsd juz nie

  3. zamkniecie socketa po jednej stronie powoduje to, ze po drugiej stronie selsct pokaze jakies dane, zas recv/send dodatkowo zwroci swoje m.in. 0 bajtow.

  4. ROB ROWNE i JEDNAKOWE WCIĘCIA, BO KOD JEST NIECZYTELNY!

0

Wersja sformatowana (też nienawidzę czytać niesformatowanego kodu), może teraz sam zobaczysz z czym masz problem:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>

void DrukujNadawce(struct sockaddr_in *adres) {
    printf("Wiadomosc od %s:%d",
            inet_ntoa(adres->sin_addr),
            ntohs(adres->sin_port));
}

int ObsluzTCP(int gniazdo, struct sockaddr_in *adres) {
    int nowe_gniazdo;
    char bufor[1024];
    socklen_t dladr = sizeof(struct sockaddr_in);
    nowe_gniazdo = accept(gniazdo, (struct sockaddr*) adres, &dladr);
    if (nowe_gniazdo < 0) {
        printf("Bledne polaczenie (accept < 0)\n");
        return;
    }

    return nowe_gniazdo;
}

int KakaTCP(int gniazdo, int tablica[], int i, struct sockaddr_in *adres) {
    int p;
    char bufor[1024];
    socklen_t dladr = sizeof(struct sockaddr_in);
    memset(bufor, 0, 1024);
    if (recv(gniazdo, bufor, 1024, 0) >= 0) {
        DrukujNadawce(adres);
        printf("[TCP]: %s\n", bufor);
        p = 0;
        while (p <= i) {
            send(tablica[p], bufor, 1024, 0);
            p = p + 1;
        }
    }
}

void ObsluzObaProtokoly(int gniazdoTCP, struct sockaddr_in *adres) {
    fd_set readfds;
    struct timeval timeout;
    int proba;
    int maxgniazdo, i, j = 0;
    int gniazdka[10];

    maxgniazdo = gniazdoTCP + 1;
    i = -1;
    proba = 0;

    while (1) {
        j = 0;
        FD_ZERO(&readfds);
        FD_SET(gniazdoTCP, &readfds);
        while (j <= i) {
            FD_SET(gniazdka[j], &readfds);
            j = j + 1;
        }
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;
        if (select(maxgniazdo, &readfds, NULL, NULL, &timeout) > 0) {
            proba = 0;
            if (FD_ISSET(gniazdoTCP, &readfds)) {
                i = i + 1;
                gniazdka[i] = ObsluzTCP(gniazdoTCP, adres);

                maxgniazdo = gniazdka[i] + 1;
            }

            while (proba <= i) {
                if (FD_ISSET(gniazdka[proba], &readfds)) {
                    KakaTCP(gniazdka[proba], gniazdka, (i), adres);
                }
                printf("proba = %d", proba);
                proba = proba + 1;
            }
        }
    }
}

int main(void) {
    struct sockaddr_in bind_me_here;
    int gt, port;

    printf("Numer portu: ");
    scanf("%d", &port);

    gt = socket(PF_INET, SOCK_STREAM, 0);

    bind_me_here.sin_family = AF_INET;
    bind_me_here.sin_port = htons(port);
    bind_me_here.sin_addr.s_addr = INADDR_ANY;

    if (bind(gt, (struct sockaddr*) &bind_me_here, sizeof(struct sockaddr_in))< 0) {
        printf("Bind na TCP nie powiodl sie.\n");
        return 1;
    }

    listen(gt, 10);

    ObsluzObaProtokoly(gt, &bind_me_here);

    return 0;
}
0

Przepraszam że odświeżam temat ale znalazł twórca rozwiązanie problemu?

1 użytkowników online, w tym zalogowanych: 0, gości: 1