PDA

View Full Version : [C++/AF_UNIX]che c'è che non va?


NA01
20-08-2006, 20:44
se uso la recvString il programma non aspetta che qualcuno mandi qualcosa e continua come se nulla fosse...
ho convertito dalle strutture originali alle stringhe per non dover includere altri sorgenti.
so che la accept apre una socket di troppo, ma per ora mi preoccupa di più il fatto che la recv non funzioni...

qualcuno mi può illuminare?
grazie, ciao!


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <iostream>
#include "Socket.h"
#include "Exceptions.h"

using namespace std;

#define DEBUG

Socket::Socket(int port){
memset (&local, 0, sizeof(struct sockaddr_un));
memset (&remote, 0, sizeof(struct sockaddr_un));
socketDescriptor = socket(PF_LOCAL, SOCK_STREAM, 0);
if(socketDescriptor < 0){
throw SocketException(__LINE__, __FILE__);
}
local.sun_family = AF_LOCAL;
strcpy (local.sun_path, "/home/luca/SOCK");
if(::bind (socketDescriptor, (sockaddr *)&local, SUN_LEN (&local)) < 0){
throw SocketException(__LINE__, __FILE__);
}
if(::listen(socketDescriptor, 5) < 0){
throw SocketException(__LINE__, __FILE__);
}
}

Socket::Socket(){
memset (&local, 0, sizeof(struct sockaddr_un));
memset (&remote, 0, sizeof(struct sockaddr_un));
socketDescriptor = socket(PF_LOCAL, SOCK_STREAM, 0);
}

Socket::~Socket(){
if(isValid()){
close(socketDescriptor);
unlink("/home/luca/SOCK");
}
}

void Socket::connect(std::string hostAddress, int port){
remote.sun_family = AF_LOCAL;
strcpy (remote.sun_path, "/home/luca/SOCK");
if(::connect(socketDescriptor, (sockaddr *)&remote, SUN_LEN(&remote) ) < 0){
throw SocketException(__LINE__, __FILE__);
}
}

Socket Socket::accept(){
if(!isValid()){
throw SocketException(__LINE__, __FILE__);
}
Socket newSocket;
socklen_t newSocketLen = 0;
newSocket.socketDescriptor = ::accept(socketDescriptor, (sockaddr*) &remote, &newSocketLen);
if(newSocket.socketDescriptor < 0){
throw SocketException(__LINE__, __FILE__);
}
cerr << newSocket.socketDescriptor << endl;
return newSocket;
}

bool Socket::isValid(){
if(socketDescriptor == -1){
return false;
}else{
return true;
}
}

std::string Socket::recvString(){
if(!isValid()){
throw SocketException(__LINE__, __FILE__);
}
char str[2048];
if(::read(socketDescriptor,str,2048) == -1){
throw SocketException(__LINE__, __FILE__);
}
return string(str);
}

void Socket::sendString(string data){
if(!isValid()){
throw SocketException(__LINE__, __FILE__);
}
if(::write(socketDescriptor, data.c_str(), 2048) == -1){
throw SocketException(__LINE__, __FILE__);
}
}

ilsensine
21-08-2006, 09:37
Senza uno straccio di main() per vedere cosa fai è dura...

Comunque correggi questi errori:

socklen_t newSocketLen = 0;

socklen_t newSocketLen = sizeof(remote);


if(::read(socketDescriptor,str,2048) == -1){
throw SocketException(__LINE__, __FILE__);
}
return string(str);
}

Se i dati letti non terminano per '\0'?


if(::write(socketDescriptor, data.c_str(), 2048) == -1){
throw SocketException(__LINE__, __FILE__);
}

Read overflow. Usa data.length()+1 al posto di 2048.

nb la accept non è superflua. Non puoi effettuare read/write su un socket in listen.

NA01
21-08-2006, 10:21
socklen_t newSocketLen = sizeof(remote);


non ho capito se serve o no... advancedlinuxprogramming non fa vedere l'inizializzazione, ma senza perror mi dice che la chiamata ha un parametro non valido.
quindi lo ho messo a 0, ma credevo che non servisse a nulla... non è la accept che lo modifica?

Se i dati letti non terminano per '\0'?

eh, salta tutto :D
le funzioni originali non mandavano stringhe ma strutture. questo lo ho messo velocemente per riprodurre l'errore senza dover passare tutti gli header delle strutture dati ;)
una volta risolto il problema propago le modifiche alla versione con le strutture e questo codice viene archiviato (c'è chi dice "buttato nel cesso :D ")

nb la accept non è superflua. Non puoi effettuare read/write su un socket in listen.
se ti riferisci alla mia frase sulla doppia socket non mi riferivo a quello.
solo che l'accept la lancio su una classe che nel costruttore ha una chiamata a socket() per poi sovrascrivere il socketDescriptor con quello restituito dalla accept.
di quello restituito da socket non se ne fa nulla nessuno, e sopratutto nessuno dice che non serve più.
intanto i costruttori vanno modificati (dai parametri credo si capisca che sto modificando una classe che usava af_inet) dato che hanno parametri inutili!

ah, se servisse la perror di read restituisce success, mentre wirite (che fallisce con -1) accusa il client di essersi scollegato.


ti riallego tutto

ecco il main del client di prova


#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <sys/un.h>
#include "Exceptions.h"
#include "Socket.h"

using namespace std;

int main()
{
try{
int tmp = 6;
size_t len = 0;
char arr[222];
Socket sock;
sock.connect("",4);
string pippo =sock.recvString();
cerr << pippo << " dfsgds" << endl;
}catch(SocketException e){
cerr << e.fileName << " " << e.lineNumber << endl;
}
return 0;
}



il main del server di prova



#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <sys/un.h>
#include "Exceptions.h"
#include "Socket.h"

using namespace std;

int main()
{
try{
Socket sock(222);
int a = 9;
sock.accept();
RequestAuthData pippo;
strcpy(pippo.programName, "suca!!");
sock.sendString("ciao!!!");
}catch(SocketException e){
cerr << e.fileName << " " << e.lineNumber << endl;
}
}


e per finire la banale implementazione di SocketException (che dovrebbe trovarsi in exceptions.h)


class SocketException{
public:
SocketException(int line, std::string file){
lineNumber = line;
fileName = file;
}
std::string fileName;
int lineNumber;
};


anzi, no... per completezza ecco il .h della classe Socket



#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>

class Socket{
public:
Socket(int port);
Socket();
~Socket();
void connect(std::string address, int port);
Socket accept();
std::string recvString();
void sendString(std::string data);
private:
int socketDescriptor;
struct sockaddr_un local, remote;
bool isValid();
};

#endif /*SOCKET_H_*/



non dovrebbe mancare nulla! :D

grazie mille, avevo il terroreche fossi in ferie :cry:

:sofico:

ilsensine
21-08-2006, 10:57
Non puoi effettuare read/write su un socket in listen.

il main del server di prova


Socket sock(222);
sock.accept();
sock.sendString("ciao!!!");


...appunto :D

nb molto "interessante" l'effetto collaterale della tua accept :D :D

ilsensine
21-08-2006, 11:04
non ho capito se serve o no... advancedlinuxprogramming non fa vedere l'inizializzazione, ma senza perror mi dice che la chiamata ha un parametro non valido.
quindi lo ho messo a 0, ma credevo che non servisse a nulla... non è la accept che lo modifica?
RTFM (M = manpage)

NA01
21-08-2006, 11:07
...appunto :D
ssssssssssssshhhhhhhhh....
non lo ho mai fatto, ok??? :D

ma sono rimbecillito, qua mi deregistrano 1000000 esami e hanno anche ragione... :eek:
ssssssssssshhhhh...
tu non hai visto NIENTE :sofico:

dai, siamo daccordo?
ti pago, ma NIENTE, ok?
:D

ilsensine
21-08-2006, 11:09
ssssssssssssshhhhhhhhh....
non lo ho mai fatto, ok??? :D

ma sono rimbecillito, qua mi deregistrano 1000000 esami e hanno anche ragione... :eek:
ssssssssssshhhhh...
tu non hai visto NIENTE :sofico:

dai, siamo daccordo?
ti pago, ma NIENTE, ok?
:D
Ok ti rimane solo da sistemare l' "interessante" effetto collaterale della tua accept :D

SerMagnus
21-08-2006, 11:09
scusate l'OT, tu che manuale/guida stai utilizzando? Ho letto AdvancedLinux programming dove posso trovarlo?

NA01
21-08-2006, 11:14
hai gapil, advancedlinuxprogramming e mille mille altri libri (spesso da comprare :D)

il secondo è molto stringato e veloce, lo trovi sull'omonimo sito (.com)
il primo è in italiano e si dilunga molto di più in spiegazioni

ciao!!!

NA01
21-08-2006, 11:17
Ok ti rimane solo da sistemare l' "interessante" effetto collaterale della tua accept :D
parli della chiamata a socket? o mi sfugge dell'altro? dopo questa dubito di tutto :D
che figura di me**a :eek:

non mi riprenderò mai :D

ilsensine
21-08-2006, 11:22
parli della chiamata a socket? o mi sfugge dell'altro? dopo questa dubito di tutto :D
che figura di me**a :eek:

non mi riprenderò mai :D
Stai ancora in vacanza :D

Hint:

Socket Socket::accept(){
Socket newSocket;
(...)
return newSocket; // oh-ho, Socket::~Socket!!!
}