Problem mit Sockets



  • hi,

    bin gerade dabei, mich mit Sockets zu beschäftigen. Habe ein Beispiel, bei dem ich über das UDP-Protokoll Daten bzw. einfache Strings austausche. Ich starte also den Sever, dann über Kommandozeilen-Argumente den Client und will dann Strings an den Server schicken, der diesen ausgibt und eine Meldung an den Client zurückgibt, dass er den Text erhalten hat.

    Problem ist nur, dass immer die Exception: Konnte Daten nicht senden ausgelöst wird und ich aber nicht versteh', wo der Fehler liegen soll.

    Hier der Code (in Visual Studio 2005 Pro erstellt):

    socket.h

    #ifndef _SOCKET_H
    #define _SOCKET_H
    #include <iostream>
    #include <Windows.h>
    #include <WinSock.h>
    #include <string>
    #include <io.h>
    using namespace std;
    
    // max. Anzahl Verbindungen
    const int MAXCONNECTIONS = 5;
    // max. Anzahl Daten, die auf einmal empfangen werden
    const int MAXRECV = 1024;
    
    class Socket
    {
    private:
    	// Socket-Deskriptor
    	int m_sock;
    	// Struktur sockaddr_in
    	sockaddr_in m_addr;
    
    public:
    	Socket();
    	~Socket();
    
    	// Socket erstellen - TCP
    	bool create();
    	// Socket erstellen - UDP
    	bool UDP_create();
    	bool bind(const int port);
    	bool listen() const;
    	bool accept(Socket&) const;
    	bool connect(const string host, const int port);
    
    	// Datenübertragung TCP
    	bool send(const string) const;
    	int recv(string&) const;
    	// Datenübertragung UDP
    	bool UDP_send(const string, const string, const int port) const;
    	int UDP_recv(string&) const;
    
    	// Socket schließen
    	bool close() const;
    	// WSACleanup()
    	void cleanup() const;
    	bool is_valid() const;
    };
    
    class SockExcept
    {
    private:
    	string except;
    
    public:
    	SockExcept(string s) : except(s) {};
    	~SockExcept() {};
    	string get_SockExcept() {return except;};
    };
    #endif
    

    socket.cpp

    #include <iostream>
    #include <Windows.h>
    #include <WinSock.h>
    #include <string>
    #include <cstdlib>
    #include "socket.h"
    using namespace std;
    
    Socket::Socket() : m_sock(0)
    {
    	// WinSock.dll initialisieren
    	WORD wVersionRequested;
    	WSADATA wsaData;
    	wVersionRequested = MAKEWORD(1, 1);
    	if (WSAStartup(wVersionRequested, &wsaData) != 0)
    	{
    		throw SockExcept("Fehler beim Initialisieren von Winsock\n");
    	}
    }
    
    Socket::~Socket()
    {
    	if (is_valid())
    		::closesocket(m_sock);
    }
    
    bool Socket::is_valid() const
    {
    	return m_sock != -1;
    }
    
    // erzeugt das Socket-TCP
    bool Socket::create()
    {
    	m_sock = (int)::socket(AF_INET, SOCK_STREAM, 0);
    	if (m_sock < 0)
    	{
    		throw SockExcept("Fehler beim Anlegen eines Socket\n");
    	}
    	return true;
    }
    
    // erzeugt das Socket-UDP
    bool Socket::UDP_create()
    {
    	m_sock = (int)::socket(AF_INET, SOCK_DGRAM, 0);
    	if (m_sock < 0)
    	{
    		throw SockExcept("Fehler beim Anlegen eines Socket\n");
    		exit(1);
    	}
    	return true;
    }
    
    // Bindung an bestimmten Port
    bool Socket::bind(const int port)
    {
    	if (!is_valid())
    	{
    		return false;
    	}
    	m_addr.sin_family = AF_INET;
    	m_addr.sin_addr.s_addr = INADDR_ANY;
    	m_addr.sin_port = htons(port);
    
    	int bind_return = ::bind(m_sock, (struct sockaddr*) &m_addr, sizeof(m_addr));
    	if (bind_return == -1)
    		return false;
    
    	return true;
    }
    
    // Socket mitteilen, dass Verbindungswünsche von Clients entgegengenommen werden
    bool Socket::listen() const
    {
    	if (!is_valid())
    		return false;
    
    	int listen_return = ::listen(m_sock, MAXCONNECTIONS);
    	if (listen_return == -1)
    		return false;
    
    	return true;
    }
    
    // Verbindungswünsche von Clients bearbeiten
    // Aufruf von accept() blockiert so lange, bis ein Client Verbindung aufnimmt
    bool Socket::accept(Socket& new_Socket) const
    {
    	int addr_length = sizeof(m_addr);
    	new_Socket.m_sock = (int)::accept(m_sock, (sockaddr*) &m_addr, (int*) &addr_length);
    
    	if (new_Socket.m_sock <= 0)
    		return false;
    	else
    		return true;
    }
    
    // baut Verbindung zum Server auf
    bool Socket::connect(const string host, const int port)
    {
    	if (!is_valid())
    	{
    		return false;
    	}
    
    	struct hostent *host_info;
    	unsigned long addr;
    	memset(&m_addr, 0, sizeof(m_addr));
    	if (addr = inet_addr(host.c_str()) != INADDR_NONE)
    	{
    		// argv[1] ist eine numerische IP_Adresse
    		memcpy((char*) &m_addr.sin_addr, &addr, sizeof(addr));
    	}
    	else
    	{
    		// Servernamen (z.B. localhost) in IP-Adresse umwandeln
    		host_info = gethostbyname(host.c_str());
    		if (NULL == host_info)
    		{
    			throw SockExcept("Unbekannter Server\n");
    			exit(1);
    		}
    		memcpy((char*) &m_addr.sin_addr, host_info->h_addr, host_info->h_length);
    	}
    
    	m_addr.sin_family = AF_INET;
    	m_addr.sin_port = htons(port);
    	int status = ::connect(m_sock, (sockaddr*) &m_addr, sizeof(m_addr));
    	if (status == 0)
    		return true;
    	else
    		return false;
    }
    
    // Daten versenden via TCP
    bool Socket::send(const std::string s) const
    {
    	int status = ::send(m_sock, s.c_str(), (int)s.size(), 0);
    	if (status == -1)
    		return false;
    	else
    		return true;
    }
    
    // Daten empfangen via TCP
    int Socket::recv(std::string &s) const
    {
    	char buf[MAXRECV+1];
    	s = "";
    	memset(buf, 0, MAXRECV+1);
    
    	int status = ::recv(m_sock, buf, MAXRECV, 0);
    	if (status > 0 || status != SOCKET_ERROR)
    	{
    		s = buf;
    		return status;
    	}
    	else
    	{
    		throw SockExcept("Fehler in Socket::recv\n");
    		exit(1);
    		return 0;
    	}
    }
    
    // Daten versenden via UDP
    bool Socket::UDP_send(const string addr, const string s, const int port) const
    {
    	struct sockaddr_in addr_sento;
    	struct hostent *h;
    	int rc;
    
    	h = gethostbyname(addr.c_str());
    	if (h == NULL)
    	{
    		throw SockExcept("Unbekannter Host\n");
    		exit(1);
    	}
    	addr_sento.sin_family = h->h_addrtype;
    	memcpy((char*) &addr_sento.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
    	addr_sento.sin_port = htons(port);
    	rc = sendto(m_sock, s.c_str(), (int)s.size(), 0, (struct sockaddr *) &addr_sento, sizeof(addr_sento));
    
    	if (rc == SOCKET_ERROR)
    	{
    		throw SockExcept("Konnte Daten nicht senden - sendto()\n");
    		exit(1);
    	}
    	return true;
    }
    
    // Daten empfangen via UDP
    int Socket::UDP_recv(std::string &s) const
    {
    	struct sockaddr_in addr_recvfrom;
    	int len, n;
    	char buf[MAXRECV+1];
    	s = "";
    	memset(buf, 0, MAXRECV+1);
    	len = sizeof(addr_recvfrom);
    	n = recvfrom(m_sock, buf, MAXRECV, 0, (struct sockaddr*) &addr_recvfrom, &len);
    
    	if (n == SOCKET_ERROR)
    	{
    		throw SockExcept("Fehler bei recvfrom()\n");
    		exit(1);
    		return 0;
    	}
    	else
    	{
    		s = buf;
    		return n;
    	}
    }
    
    // Winsock.dll freigeben
    void Socket::cleanup() const
    {
    	WSACleanup();
    }
    
    // Socket schließen und Winsock.dll freigeben
    bool Socket::close() const
    {
    	closesocket(m_sock);
    	cleanup();
    	return true;
    }
    

    Main.cpp (vom Server

    #include <iostream>
    #include <string>
    #include "socket.h"
    using namespace std;
    
    int main()
    {
    	try
    	{
    		Socket server;
    		server.UDP_create();
    		server.bind(14000);
    		cout << "Server wartet auf Daten..." << endl;
    		try
    		{
    			while (true)
    			{
    				string s;
    				server.UDP_recv(s);
    				cout << "Daten erhalten: " << s << endl;
    			}
    		}
    		catch (SockExcept &) {}
    	}
    	catch (SockExcept &e)
    	{
    		cout << "Exception: " << e.get_SockExcept() << endl;
    	}
    	cin.get();
    	return 0;
    }
    

    client.cpp

    #include <iostream>
    #include <string>
    #include "socket.h"
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	if (argc < 3)
    	{
    		cout << "Usage: " << argv[0] << " <server> <string>" << endl;
    		//exit(1);
    	}
    	try
    	{
    		Socket client;
    		client.UDP_create();
    		client.bind(14000);
    		string argv_1 = argv[1];
    		string argv_2 = argv[2];
    		client.UDP_send(argv_1, argv_2, 14000);
    	}
    	catch (SockExcept &e)
    	{
    		cout << "Exception: " << e.get_SockExcept() << endl;
    	}
    	return 0;
    }
    

    Vllt hab ihr noch weitere Hinweise zu dem Code, was vllt schlecht gelöst ist...
    Hoffe, ihr könnt mir helfen und habt verstanden, was ich meine 🙂 .

    thx im voraus

    mfg R3dNeXX


Anmelden zum Antworten