C Simples Client-to-Client Chat Programm ohne zwischenliegendem Server

XHotSniperX

Lt. Junior Grade
Registriert
Jan. 2008
Beiträge
472
Hi Leuteeeeee was geht ab

ich möchte ein simples Chatprogramm machen, wie im Titel beschrieben. Hier habe ich mit einem kleinen Testprogramm angefangen:

Code:
#include <sys/types.h>    // für socket()
#include <sys/socket.h>   // für socket()
#include <netinet/in.h>   // für socket()
#include <assert.h>       // für assert()
#include <stdlib.h>       //für calloc()
#include <netdb.h>        // für getprotobyname()
#include <unistd.h>       // für close()
#include <arpa/inet.h>    //für inet_ntop()
#include <netinet/in.h>   //für INET_ADDRSTRLEN
#include <string.h>       // für memset()
#include <stdio.h>
 
int main(int argc, char *argv[]) {
	/* Socket erstellen - TCP, IPv4, keine Optionen */
	printf("Erstellt Socket...\n");
	int lsd = socket(AF_INET, SOCK_STREAM, 0);
 
	/* IPv4, Port: argv[2], IP-Adresse: argv[1] */
	printf("Socketadresse uebernehmen...\n");
	struct sockaddr_in saddr;
	bzero(&saddr, sizeof(saddr));
	inet_pton(AF_INET, argv[1], &(saddr.sin_addr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons((int)*argv[2]);
 
	/* Socket an Port binden */
	printf("Socket an Port binden...\n");
	bind(lsd, (struct sockaddr*) &saddr, sizeof(saddr));
 
	/* Auf Socket horchen (Listen) */
	printf("Auf Socket horchen...\n");
	listen(lsd, 10);
 
	while(1) {
		/* Puffer und Strukturen anlegen */
		struct sockaddr_in clientaddr;
		char buffer[10];
		bzero(buffer, sizeof(buffer));
		
		/* Verbindung aufbauen, bin ich der erste? */
		if(connect(lsd, (struct sockaddr*) &saddr, sizeof(saddr)) == 0) {
			printf("Erfolgreich mit Partner connected...\n");
			/* Puffer mit Text füllen */
			char buffer[5];
			strcpy(buffer, "test");
		 
			/* "test" String an Partnerclient senden */
			int bytes = send(lsd , buffer, sizeof(buffer), 0);
		 
			/* Ausgabe was gesendet wurde */
			printf("Sende String: %s\n", buffer);
			printf("Es wurden %d Bytes gesendet\n", bytes);			
		}
		else {
			printf("Konnte nicht mit Partner connecten...\n");
		}
 
		/* Auf Verbindung warten, bei Verbindung Connected-Socket erstellen */
		printf("Auf Verbindung warten...\n");
		socklen_t clen = sizeof(clientaddr);
		int csd = accept(lsd, (struct sockaddr*) &clientaddr, &clen);
 
		/* Vom Client lesen und ausgeben */
		int bytes = recv(csd, buffer, sizeof(buffer), 0);
		printf("Der Client hat folgenden String gesendet: %s\n", buffer);
		printf("Es wurden %d Bytes empfangen\n", bytes);
 
		/* Verbindung schließen */
		close(csd);
	}
 
	close(lsd);
	return 0;
 
}

Das Problem ist, wenn ich beide Programme starte mit der IP-Adresse "127.0.0.1" und Port "6666" (oder auch zwei verschiedene Ports), dann stecken beide Programme im accept fest und keiner schafft das connect().

Was muss ich ändern, damit beide Clients miteinander verbinden können und einfach Nachrichten erhalten können (was dann später mit Threads oder so realisierbar wäre)? :cool_alt:
 
Du hast das Problem und die Lösung im Grunde beide genannt.

Accept blockiert. Also muss das in einen Thread...
 
GrinderFX schrieb:
Da braucht mein keine Threads. Nimm einfach die select Funktion.

Genau. Den listening file descriptor des accepts und den file descriptor den du mit read und write ausliest bzw beschreibst mit select/poll/epoll/kqueue oder iocp beobachten. Dann kannst du alles innerhalb des mainthreads laufen lassen
 
Sorry, aber er hat das Grundproblem nicht gelöst. Wenn beide Programme accept() aufrufen, dann ist es als wenn zwei Leute vor dem Telefon sitzen und darauf warten, dass der andere anruft, so kommen sie also niemals in ein Gespräch. Einer muss ein connect() aufrufen während der andere bei accept() wartet, damit eine Verbindung hergestellt werden kann. So sieht das aus:

socket_client_server.gif
 
@Holt
Wenn es dem Autor schon an diesem Verständnis fehlt, sollte er vielleicht noch mal von ganz von vorne anfangen.
 
Ich habe meine Frage schlecht ausgedruckt. Dass accept() logischerweise beide blockiert ist mir klar. Zwei verschiedene Programme (Server, Client) möchte ich nicht haben, sondern nur eines. Eine direkte Verbindung zwischen zwei Clients.
Mein Ziel ist es, dass der erste, der das Programm startet einfach mal überprüft (connect()), ob der Partner bereits da ist oder nicht, wenn nein dann soll er einfach beim accept() warten. Der andere, der als zweiter das Programm startet soll sich dann connecten können. Danach sollten sie miteinander chatten können. Und wieso verbindet sich das später gestartete Programm nicht mit connect(), wenn doch der andere bereits am warten ist? Wo ist da der Fehler?
 
Halte dich "einfach" an bestehende Standards, nutz z.B. das Bonjour-Protokol. Das bietet genau das, was du willst (und mehr).
 
Ich hab zwar keine Ahnung von programmieren, aber ich versteh nicht warum du zu 127.0.0.1, also localhost, connecten willst, wer oder was soll da antworten? Müsstest da nicht die IP deines Gegenüber nehmen?
Wie gesagt versteh ich das nicht, oder ich versteh irgendwas grundsätzlich nciht, dann sorry für meine Zwischenfrage. :)
 
weil beide clients auf dem gleichen pc laufen :) dann haben sie die gleiche adresse. sonst wäre das natürlich nicht localhost
 
Ich habe nun das komplett sinnlose Programm geändert. Jetzt ist es intern in Server und Client unterteilt, anhand der Parameter, welche noch nicht implementiert sind. Hab jetzt select() für Empfang und Standardinput-Sendung benutzt.
Der Verbindungsaufbau scheint zu klappen, wenn ich das Programm nacheinander zweimal starte (zu erst mit 2 Argumenten und dann mit 3). Allerdings klappt das chatten noch nicht fehlerfrei. Wenn ich beim "Server" etwas schreibe und Enter drücke, dann gibts beim Server einen segmentation fault-Fehler und beim "Client" eine Endlosschleife der Empfangausgabe. Dabei kommt da immer wieder ein leerer String mit 0 Bytes.

Code:
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <assert.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#define STDIN 0
#define BUFFERSIZE 110

int main(int argc, char *argv[]) {
	if(argc == 2) {
		/* Socket erstellen - TCP, IPv4, keine Optionen */
		int lsd = socket(AF_INET, SOCK_STREAM, 0);
	 
		/* IPv4, Port: 1111, jede IP-Adresse akzeptieren */
		struct sockaddr_in saddr;
		saddr.sin_family = AF_INET;
		saddr.sin_port = htons(1111);
		saddr.sin_addr.s_addr = htons(INADDR_ANY);
	 
		/* Socket an Port binden */
		bind(lsd, (struct sockaddr*) &saddr, sizeof(saddr));
	 
		/* Auf Socket horchen (Listen) */
		listen(lsd, 10);
	 
		while(1) {
			/* Puffer und Strukturen anlegen */
			struct sockaddr_in clientaddr;
			char buffer[BUFFERSIZE];
			bzero(buffer, sizeof(buffer));
			char *my_string;
			size_t len = BUFFERSIZE-2;
	 
			/* Auf Verbindung warten, bei Verbindung Connected-Socket erstellen */
			socklen_t clen = sizeof(clientaddr);
			int csd = accept(lsd, (struct sockaddr*) &clientaddr, &clen);
			
			/* File Descriptor erstellen für "parallele" Verarbeitung */
			/* von recv() aus csd und send() eines inputs auf csd     */
			fd_set fds;
			int maxfd = (csd > STDIN)?csd:STDIN;
			while(1) {
				FD_ZERO(&fds);
				FD_SET(csd, &fds); 
				FD_SET(STDIN, &fds); 
				select(maxfd+1, &fds, NULL, NULL, NULL); 
				if(FD_ISSET(STDIN, &fds)) {
					/* Von Standardinput lesen und senden */
					getline(&my_string, &len, stdin);
					int bytes = send(csd, my_string, strlen(my_string), 0);
					
					/* Ausgabe was gesendet wurde */
					printf("Sende String: %s\n", my_string);
					printf("Es wurden %d Bytes gesendet\n", bytes);
				}
				if(FD_ISSET(csd, &fds)) {
					/* Vom Client lesen und ausgeben */
					int bytes = recv(csd, buffer, sizeof(buffer), 0);
					printf("Der Client hat folgenden String gesendet: %s\n", buffer);
					printf("Es wurden %d Bytes empfangen\n", bytes);
				}
			}
	 
			/* Verbindung schließen */
			close(csd);
		}
	 
		close(lsd);
		return EXIT_SUCCESS;
	}
	
/******************************************************************************/

	else if(argc == 3) {
		/* Socket erstellen */
		int socks = socket(AF_INET, SOCK_STREAM, 0);
	 
		/* Verbindungsziel festlegen, Port und IP-Adresse des Servers angeben */
		struct sockaddr_in serveraddr;
		bzero(&serveraddr, sizeof(serveraddr));
		inet_pton(AF_INET, "127.0.0.1", &(serveraddr.sin_addr));
		serveraddr.sin_family = AF_INET;
		serveraddr.sin_port = htons(1111);
	 
		/* Verbindung aufbauen */
		connect(socks, (struct sockaddr*) &serveraddr, sizeof(serveraddr));
		
		/* Puffer und Strukturen erstellen */
		char buffer[BUFFERSIZE];
		char *my_string;
		size_t len = BUFFERSIZE-2;
		
		/* File Descriptor erstellen für "parallele" Verarbeitung  */
		/* von recv() aus socks und send() eines inputs auf socks  */
		fd_set fds;
		int maxfd = (socks > STDIN)?socks:STDIN;
		while(1) {
			FD_ZERO(&fds);
			FD_SET(socks, &fds); 
			FD_SET(STDIN, &fds); 
			select(maxfd+1, &fds, NULL, NULL, NULL); 
			if(FD_ISSET(STDIN, &fds)) {
				/* Von Standardinput lesen und senden */
				getline(&my_string, &len, stdin);
				int bytes = send(socks, my_string, strlen(my_string), 0);
				
				/* Ausgabe was gesendet wurde */
				printf("Sende String: %s\n", my_string);
				printf("Es wurden %d Bytes gesendet\n", bytes);
			}
			if(FD_ISSET(socks, &fds)) {
				/* Vom Client lesen und ausgeben */
				int bytes = recv(socks, buffer, sizeof(buffer), 0);
				printf("Der Server hat folgenden String gesendet: %s\n", buffer);
				printf("Es wurden %d Bytes empfangen\n", bytes);
			}
		}
	 
		/* Verbindung beenden */
		close(socks);
	 
		return EXIT_SUCCESS;
	}
}
 
Der Absturz dürfte hier seine Ursache haben:
char *my_string;
...
getline(&my_string, &len, stdin);

Der pointer zeigt auf keine gültige Adresse und ist nicht NULL. Schau in die man pages:
If *lineptr is NULL, then getline() will allocate a buffer for storing the
line, which should be freed by the user program. (In this case, the value
in *n is ignored.)

Alternatively, before calling getline(), *lineptr can contain a pointer to
a malloc(3)-allocated buffer *n bytes in size. If the buffer is not large
enough to hold the line, getline() resizes it with realloc(3), updating
*lineptr and *n as necessary.
Wenn Du mit dem Englischen Probleme hast, dann lerne die Sprache, wenn ohne bist Du verloren! Eine technische Dokumentation in englisch musst Du genauso gut verstehen wie eine die auf Deutsch ist.

Hier Dein leicht angepasster Code, so dass er funktioniert, sogar unter Windows:
Code:
#include <stdio.h>
#ifdef WIN32
#include "winsock.h"
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <assert.h>
#include <stdlib.h>
#ifdef WIN32
#define bzero(a, b) memset(a, 0, b) 
typedef int   socklen_t;
typedef long  ssize_t;
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
{
	int c;
	unsigned int cnt=0;
	if (*lineptr == NULL)
		*lineptr = (char *)malloc(*n = 256);
	while(((c = fgetc(stream))!= EOF) && (c != '\n'))
	{
		(*lineptr)[cnt++]=(char)c;
		if (cnt == *n)
			*lineptr = (char *)realloc(*lineptr, (*n)*=2);
	}
	if(c == '\n')
		(*lineptr)[cnt++]=(char)c;
	(*lineptr)[cnt] = '\0';
	return cnt;
}
void close(int sck) {closesocket(sck);}
//Vista und höher: #include <Ws2tcpip.h>
int inet_pton(int af, const char *src, struct in_addr *dst)
{
	dst->S_un.S_addr = inet_addr(src);
	return 0;
}
#pragma comment(lib, "Ws2_32.lib")
#else
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#endif
#include <string.h>
#include <errno.h>
#define STDIN 0
#define BUFFERSIZE 110

int main(int argc, char *argv[]) {
#ifdef WIN32
	WSADATA wsaData;
    // Initialize Winsock
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }
#endif
	if(argc == 2) {
		/* Socket erstellen - TCP, IPv4, keine Optionen */
		int lsd = socket(AF_INET, SOCK_STREAM, 0);
	 
		/* IPv4, Port: 1111, jede IP-Adresse akzeptieren */
		struct sockaddr_in saddr;
		saddr.sin_family = AF_INET;
		saddr.sin_port = htons(1111);
		saddr.sin_addr.s_addr = htons(INADDR_ANY);
	 
		/* Socket an Port binden */
		bind(lsd, (struct sockaddr*) &saddr, sizeof(saddr));
	 
		/* Auf Socket horchen (Listen) */
		listen(lsd, 10);
		size_t len = BUFFERSIZE-2;
		char *my_string = (char *)malloc(len);
		while(1) {
			/* Puffer und Strukturen anlegen */
			struct sockaddr_in clientaddr;
			char buffer[BUFFERSIZE];
			bzero(buffer, sizeof(buffer));
	 
			/* Auf Verbindung warten, bei Verbindung Connected-Socket erstellen */
			socklen_t clen = sizeof(clientaddr);
			int csd = accept(lsd, (struct sockaddr*) &clientaddr, &clen);
			
			/* File Descriptor erstellen für "parallele" Verarbeitung */
			/* von recv() aus csd und send() eines inputs auf csd     */
			fd_set fds;
			int maxfd = (csd > STDIN)?csd:STDIN;
			while(1) {
				FD_ZERO(&fds);
				FD_SET(csd, &fds); 
				FD_SET(STDIN, &fds); 
				select(maxfd+1, &fds, NULL, NULL, NULL); 
				if(FD_ISSET(STDIN, &fds)) {
					/* Von Standardinput lesen und senden */
					getline(&my_string, &len, stdin);
					int bytes = send(csd, my_string, strlen(my_string)+1, 0);
					
					/* Ausgabe was gesendet wurde */
					printf("Sende String: %s\n", my_string);
					printf("Es wurden %d Bytes gesendet\n", bytes);
				}
				if(FD_ISSET(csd, &fds)) {
					/* Vom Client lesen und ausgeben */
					int bytes = recv(csd, buffer, sizeof(buffer), 0);
					printf("Der Client hat folgenden String gesendet: %s\n", buffer);
					printf("Es wurden %d Bytes empfangen\n", bytes);
				}
			}
	 
			/* Verbindung schließen */
			close(csd);
			free(my_string);
		}
		
		close(lsd);
		return EXIT_SUCCESS;
	}
	
/******************************************************************************/

	else if(argc == 3) {
		/* Socket erstellen */
		int socks = socket(AF_INET, SOCK_STREAM, 0);
	 
		/* Verbindungsziel festlegen, Port und IP-Adresse des Servers angeben */
		struct sockaddr_in serveraddr;
		bzero(&serveraddr, sizeof(serveraddr));
		inet_pton(AF_INET, "127.0.0.1", &(serveraddr.sin_addr));
		serveraddr.sin_family = AF_INET;
		serveraddr.sin_port = htons(1111);
	 
		/* Verbindung aufbauen */
		connect(socks, (struct sockaddr*) &serveraddr, sizeof(serveraddr));
		
		/* Puffer und Strukturen erstellen */
		char buffer[BUFFERSIZE];
		size_t len = BUFFERSIZE-2;
		char *my_string = (char *)malloc(len);
		
		/* File Descriptor erstellen für "parallele" Verarbeitung  */
		/* von recv() aus socks und send() eines inputs auf socks  */
		fd_set fds;
		int maxfd = (socks > STDIN)?socks:STDIN;
		while(1) {
			FD_ZERO(&fds);
			FD_SET(socks, &fds); 
			FD_SET(STDIN, &fds); 
			select(maxfd+1, &fds, NULL, NULL, NULL); 
			if(FD_ISSET(STDIN, &fds)) {
				/* Von Standardinput lesen und senden */
				getline(&my_string, &len, stdin);
				int bytes = send(socks, my_string, strlen(my_string)+1, 0);
				
				/* Ausgabe was gesendet wurde */
				printf("Sende String: %s\n", my_string);
				printf("Es wurden %d Bytes gesendet\n", bytes);
			}
			if(FD_ISSET(socks, &fds)) {
				/* Vom Client lesen und ausgeben */
				int bytes = recv(socks, buffer, sizeof(buffer), 0);
				printf("Der Server hat folgenden String gesendet: %s\n", buffer);
				printf("Es wurden %d Bytes empfangen\n", bytes);
			}
		}
		free(my_string);
	 
		/* Verbindung beenden */
		close(socks);
	 
		return EXIT_SUCCESS;
	}
	return 0;
}
Wie Du aber schnell feststellen wirst, ist das kein schönes Chat Programm, weil jeder immer abwechselnd eine Eingabe machen muss. Nimm also entweder None-Blocking Aufrufe und prüfe ob etwas im Puffer steht oder mache zwei Verbindungen auf, damit beide beliebig senden und empfangen können.
 
Ah ja danke, getline() braucht nen Nullpointer. Hab die Manpage nicht ganz gelesen heieiei. Mit char *my_string = NULL; klappt es nun fast perfekt. Wieso meinst du, kann man nur abwechselnd schreiben? Es geht auch nicht abwechselnd. Aber es kann zu komischen Zeichen führen. Das Beenden muss auch noch implementiert werden hehe:




Edit: So funzt es nun perfekt auch mit beenden :)

Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <assert.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#define STDIN 0
#define BUFFERSIZE 110

int main(int argc, char *argv[]) {
	if(argc == 2) {
		/* Socket erstellen - TCP, IPv4, keine Optionen */
		int lsd = socket(AF_INET, SOCK_STREAM, 0);
	 
		/* IPv4, Port: 1111, jede IP-Adresse akzeptieren */
		struct sockaddr_in saddr;
		saddr.sin_family = AF_INET;
		saddr.sin_port = htons(1111);
		saddr.sin_addr.s_addr = htons(INADDR_ANY);
	 
		/* Socket an Port binden */
		bind(lsd, (struct sockaddr*) &saddr, sizeof(saddr));
	 
		/* Auf Socket horchen (Listen) */
		listen(lsd, 10);
	 
		while(1) {
			/* Puffer und Strukturen anlegen */
			struct sockaddr_in clientaddr;
			char buffer[BUFFERSIZE];
			bzero(buffer, sizeof(buffer));
			char *my_string = NULL;
			size_t len = BUFFERSIZE-2;
	 
			/* Auf Verbindung warten, bei Verbindung Connected-Socket erstellen */
			socklen_t clen = sizeof(clientaddr);
			int csd = accept(lsd, (struct sockaddr*) &clientaddr, &clen);
			
			/* File Descriptor erstellen für "parallele" Verarbeitung */
			/* von recv() aus csd und send() eines inputs auf csd     */
			fd_set fds;
			int maxfd = (csd > STDIN)?csd:STDIN;
			while(1) {
				FD_ZERO(&fds);
				FD_SET(csd, &fds); 
				FD_SET(STDIN, &fds); 
				select(maxfd+1, &fds, NULL, NULL, NULL); 
				if(FD_ISSET(STDIN, &fds)) {
					/* Von Standardinput lesen und senden */
					getline(&my_string, &len, stdin);
					int bytes = send(csd, my_string, strlen(my_string), 0);
					
					/* Ausgabe was gesendet wurde */
					printf("Sende String: %s\n", my_string);
					printf("Es wurden %d Bytes gesendet\n", bytes);
					memset(my_string, '\0', sizeof(my_string));
				}
				if(FD_ISSET(csd, &fds)) {
					/* Vom Client lesen und ausgeben */
					int bytes = recv(csd, buffer, sizeof(buffer), 0);
					if(bytes == 0) {
						printf("Fertig\n");
						break;
					}
					printf("Der Client hat folgenden String gesendet: %s\n", buffer);
					printf("Es wurden %d Bytes empfangen\n", bytes);
					memset(buffer, '\0', sizeof(buffer));
				}
			}
	 
			/* Verbindung schließen */
			close(csd);
		}
	 
		close(lsd);
		return EXIT_SUCCESS;
	}
	
/******************************************************************************/

	else if(argc == 3) {
		/* Socket erstellen */
		int socks = socket(AF_INET, SOCK_STREAM, 0);
	 
		/* Verbindungsziel festlegen, Port und IP-Adresse des Servers angeben */
		struct sockaddr_in serveraddr;
		bzero(&serveraddr, sizeof(serveraddr));
		inet_pton(AF_INET, "127.0.0.1", &(serveraddr.sin_addr));
		serveraddr.sin_family = AF_INET;
		serveraddr.sin_port = htons(1111);
	 
		/* Verbindung aufbauen */
		connect(socks, (struct sockaddr*) &serveraddr, sizeof(serveraddr));
		
		/* Puffer und Strukturen erstellen */
		char buffer[BUFFERSIZE];
		char *my_string = NULL;
		size_t len = BUFFERSIZE-2;
		
		/* File Descriptor erstellen für "parallele" Verarbeitung  */
		/* von recv() aus socks und send() eines inputs auf socks  */
		fd_set fds;
		int maxfd = (socks > STDIN)?socks:STDIN;
		while(1) {
			FD_ZERO(&fds);
			FD_SET(socks, &fds); 
			FD_SET(STDIN, &fds); 
			select(maxfd+1, &fds, NULL, NULL, NULL); 
			if(FD_ISSET(STDIN, &fds)) {
				/* Von Standardinput lesen und senden */
				getline(&my_string, &len, stdin);
				int bytes = send(socks, my_string, strlen(my_string), 0);
				
				/* Ausgabe was gesendet wurde */
				printf("Sende String: %s\n", my_string);
				printf("Es wurden %d Bytes gesendet\n", bytes);
				memset(my_string, '\0', sizeof(my_string));
			}
			if(FD_ISSET(socks, &fds)) {
				/* Vom Client lesen und ausgeben */
				int bytes = recv(socks, buffer, sizeof(buffer), 0);
				if(bytes == 0) {
					printf("Fertig\n");
					break;
				}
				printf("Der Server hat folgenden String gesendet: %s\n", buffer);
				printf("Es wurden %d Bytes empfangen\n", bytes);
				memset(buffer, '\0', sizeof(buffer));
			}
		}
	 
		/* Verbindung beenden */
		close(socks);
	 
		return EXIT_SUCCESS;
	}
}
 
Zuletzt bearbeitet:
Die komischen Zeichen kommen von getline(&my_string, &len, stdin);
Du ignorierst den Rückgabewert und der gibt an, wie viele Zeichen dort eingelesen werden, len ist nur die Länge des Puffers und der dürfte immer dem Wert der längsten Zeile entsprechen, die bisher eingelesen wurde. Wenn Du NULL übergibst, dann musst Du den Puffer übrigens am Ende mit free(my_string); freigeben.
Nenne also len in buflen um, also:

...
size_t buflen = 0; // das ist nur die Länge des Puffer zum Einleisen
...
while(1)
{
...
size_t len = getline(&my_string, &buflen, stdin);
int bytes = send(socks, my_string, strlen(my_string)+1, 0);
...
}
free (my_string);
Dann schicke auch nicht int bytes = send(socks, my_string, strlen(my_string), 0) sondern
int bytes = send(socks, my_string, strlen(my_string)+1, 0), damit hast Du die '\0' als letztes Zeichen des String dann auch mit übertragen und somit einen terminierten String.

Damit sollten Deine komischen Zeichen weg sein.
 
Zuletzt bearbeitet:
Holt schrieb:
free (my_string);

Wenn du das machst, solltest du denk ich auch den Wert von my_string auf NULL setzen. getline erwartet ja wieder n NULL-Pointer, wenn man nur free'd, zeigt der Pointer ja noch auf den alten Ort.
 
lies mal die man page von getline, da steht es doch ganz genau drin. getline erwartet einen mit malloc allozierte Puffer und dessen Länge. Dieser wird mit realloc erweitert, wenn er zu klein ist oder alloziert ihn eben mit malloc, wenn ein NULL Pointer übergeben wird. In jedem Fall muss man den pointer hinterher mit free freigeben. Man kann das jedesmal in getline machen (dann aber immer einen NULL Pointer übergeben) oder eben nur einmal. In jedem Fall ist aber der zweite Parameter die Länge des Puffers und nicht die Anzahl der gelesenen Zeichen, die ist der Rückgabewert von getline und den sollte man daher nicht ignorieren.
 
Zurück
Oben