Socketprogrammierung Probs (in C)

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
snowcrash
Beiträge: 168
Registriert: 28.01.2002 17:17:51

Socketprogrammierung Probs (in C)

Beitrag von snowcrash » 23.02.2002 16:20:40

Hi ich hab n paar Probleme mit Sockets unter C.

Ich hab n einfachen Server geschrieben, der auch brav Daten empfängt, aber noch jede Menge Mist dazu.
Sowohl, wenn ich mich mit telnet, als auch mit nem selbstgeschriebenen Client zum Server connecte.
Ich post mal die Quellcodes, vielleicht kann mir ja jemand helfen.

Server:

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*Netzwerk includes*/
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

/*meine defines:*/
#define MYPORT 2323

int main ()
{	
	/*Reihenfolge:
	*socket();
	*bind();
	*listen();
	*accept();
	*/
		
	/* bei error wird immer ____"-1"_________ zurückgegeben!!!*/
	int meinsocket, deinsocket; 			//sockets sind vom type int, nur nochmal zur erinnerung
	int error1, error2, error3;
	int sin_size, laenge, bytes_sent, bytes_recvd;
	int yes=1; /*des is fürs saubermachen vom Port*/
	
	char *msg = "Sie koennen bis zu 20 Zeichen an den Server senden\n";
	char recvbuffer[20];
	
	struct sockaddr_in my_addr;
	struct sockaddr_in dei_addr;
	
	
	my_addr.sin_family 	= AF_INET;    				// host byte order
	my_addr.sin_port 	= htons(MYPORT);    			// short, network byte order
	my_addr.sin_addr.s_addr = INADDR_ANY;
	memset(&(my_addr.sin_zero), '\0', 8); 				// zero the rest of the struct

	
	/*ERRORCHECK socket()*/
	if(meinsocket = socket(AF_INET, SOCK_STREAM, 0))
	 	puts("Yo man, socket >>meinsocket<< is ready for watsitsname!");
	else
		puts("Fuck! Couldn't tha m****fcking socket()!!");
	
		/* Saubermachen vom Port MYPORT*/
		if (setsockopt(meinsocket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) 
			{
			perror("setsockopt");
			exit(1);
			}
	
	/*ERROR CHECK bind()*/
	error1 = bind(meinsocket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
	if(error1 == -1)
		{
		printf("bind()! und die errornummer ist: %i\n", error1);
		exit(1);
		}
	
	/*ERROR CHECK listen() */
	error2 = listen(meinsocket, 5);	
	if(error2 == -1)
		{
		printf("listen() der error ist: %i \n", error2);
		exit(1);
		}
	
	
	/*accept() Schleife */
	while (1)
	{
		sin_size=sizeof(struct sockaddr_in); /*sin_size bezeichnet die Größe von sockaddr_in*/

		if(deinsocket = accept(meinsocket, &dei_addr, &sin_size))
			{
			printf("Client Connection! \n\n\n\n");
			laenge = strlen(msg);
			bytes_sent = send(deinsocket, msg, laenge, 0);
			if (bytes_sent < laenge)
				{
				puts("Couldn't sent all data!");
				exit(0);
				}
			else
				{	
				puts("Juhu, accept()ed!!\n");
				printf("bytes_sent: %i & laenge: %i\n", bytes_sent, laenge);
				do
					{
					bytes_recvd = recv(deinsocket, recvbuffer, sizeof(recvbuffer), 0);
					recvbuffer[bytes_recvd] = "\0";
					fflush(stdout);
					printf("\n%i Bytes empfangen!\n\nFollowing Message received:\n\n>> %s", bytes_recvd, recvbuffer);
					fflush(stdout);
					} while (recvbuffer != "quit  "); /*schwerer Fehler: recvbuffer kann NIE = "quit" werden sobald 
									  der client einmal disconnected hat -> endlosschleife. Fehler wird
									  später behoben*/
				puts ("Client exit!");
				close (deinsocket);
				exit(0);
				}
			}
		else
			puts("shit happens, not accept()ed");
	} /*while ende	*/
return (0);
}
Client:

Code: Alles auswählen

#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define DEST_IP  "192.168.0.2"
#define DEST_PORT 2323
main()
{
	int sockfd; /*deskriptor*/
	int bytes_sent, laenge, bytes_recvd;
	
	char sent_buffer[20], recv_buffer[1024];
	
	struct sockaddr_in dest_addr;    		// will hold the destination addr
	
	dest_addr.sin_family = AF_INET;    		// host byte order
	dest_addr.sin_port = htons(DEST_PORT);    	// short, network byte order
	dest_addr.sin_addr.s_addr = inet_addr(DEST_IP);
	memset(&(dest_addr.sin_zero), '\0', 8); 	// zero the rest of the struct


	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) != -1 )
		{
		bytes_recvd=recv(sockfd, recv_buffer, sizeof(recv_buffer), 0);
		printf("%i Bytes empfangen, Welcome-Message:\n\n%s\n\n\nBitte geben sie jetzt ihre Nachricht ein:\n", bytes_recvd, recv_buffer); 
		while(1)
			{
			gets(sent_buffer);
			laenge=sizeof(sent_buffer);
			sent_buffer[laenge] = "\0";
			bytes_sent = send(sockfd, sent_buffer, strlen(sent_buffer), 0);
			printf("Die Nachricht:\n\n%s\n\n%i Bytes wurden an den Server gesendet!\n\n",sent_buffer, bytes_sent);
			}
		}
	
	else
		puts("Holy shit it doesnt work and i dont know why!");

return (0);
}

snowcrash

Benutzeravatar
snowcrash
Beiträge: 168
Registriert: 28.01.2002 17:17:51

Beitrag von snowcrash » 24.02.2002 21:43:34

Für alle die wissen wollen wie's ausgegangen ist:

Es liegt an der Zeile:

Code: Alles auswählen

recvbuffer[bytes_recvd] = "\0";
Jaha, C ist eine gemeine Sprache. Die Anführungszeichen sind nämlich sehr, sehr bös und versauen einem alles!
Richtig muss es heißen:

Code: Alles auswählen

recvbuffer[bytes_recvd] = '\0';
Ach ja, der recvbuffer war bei meinem Beispiel etwas klein gewählt. 1024 anstatt 20 Bytes sind angemessen.

Und weil ich mich so gefreut hab, dass es funktioniert hier noch was nützliches:
Das "quit" Kommando, funktioniert in meinem obigen Codebeispiel nicht.
Das hab ich so gelöst:

Code: Alles auswählen


#define QUIT_CMD "quit\r\n" /*erstmal n define, um das Kommando festzulegen*/
...
...
/*do-while schleife:*/
do
{
some_stuff;
}
while(strcmp (recvbuffer, QUIT_CMD) != 0)
Dabei ist das \r\n im QUIT_CMD besonders wichtig, da der Tastendruck auf Enter, als diese beiden Zeichen mitgeschickt wird.
Sieht man auch deutlich an der Ausgabe, wieviel Byte empfangen wurden.
Es sind immer 2 mehr, als der Text Zeichen lang. (Dabei ist das \x immer 1 Byte groß)

So genug für heute.

mfg
snowcrash

Antworten