简体   繁体   中英

How to accept a custom Socket?

Im experiencing with Sockets & ServerSockets, I made a subclass from a java.net.Socket (CustomSocket) and I want to know what should I do to recreate the Socket when the ServerSocket receives the connection something like:

CustomSocket cs = CustomServerSocket.accept();

I need "cs" to be identical to the CustomSocket that requested the connection to the CustomServerSocket, 'cause I need to know in the server side the String ID of the socket that requested the connection by doing:

cs.getId(); //(shoud return the ID, but returns an empty String)

Here is the CustomServerSocket code:

        package negocio;

    import java.io.IOException;
    import java.net.Socket;
    import java.net.SocketException;
    import java.net.UnknownHostException;

    public class CustomSocket extends Socket{
        private String id;


        public CustomSocket(String host, int puerto, String id) throws UnknownHostException, IOException{
            super(host, puerto);
            this.id = id;
        }

        public CustomSocket(String host, int puerto) throws UnknownHostException, IOException{
            super(host, puerto);
            this.id = "";

        }

        public CustomSocket(){
            super();
            this.id = "";
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String toString(){
            return "cSocket ID: "+this.id;
        }
    }

and Here is the CustomServerSocket code:

package negocio;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.SocketException;

public class CustomServerSocket extends ServerSocket {



    public CustomServerSocket(int puerto) throws IOException{
        super(puerto);
    }

    @override
    public CustomSocket accept() throws IOException{
        if(this.isClosed()){
            throw new SocketException("Socket is closed");
        }
        if(!this.isBound()){
            throw new SocketException("Socket is not bound yet");
        }   
        CustomSocket ms = new CustomSocket();
        this.implAccept(ms);
        return ms;
    }
}

At first, think about the relation you need. Your CustomSocket seems to be a client in Client/Server application. Are you sure that is-a relationship must be used? Your custom class is designed for the purpose of sending data to ServerSocket. It should have Socket to make it's job, but there is no necessity to be a Socket. So has-a relationship is a preffered way to design your app. In general, avoid subclassing from classes that are not designed for that purpose. SocketServer and Socket are not designed for subclassing (usually, if class is designed for subclassing it is indicated in documentation for that class). There are no benefits of such subclassing. Instead you application become less flexible.

At second, Socket and ServerSocket use Streams to transfer data to each other. Simply transfer in Stream all the necessary info you need from Socket to ServerSocket.

I avoid boilerplate code for the sake of brevity.

public class Client {
private String id;
private Socket socket;

public Client(final Socket socket, final String id) {
    this.socket = socket;
    this.id = id;
}

void sendData() {
    try (DataOutputStream idToSend = new DataOutputStream(socket.getOutputStream())) {

        idToSend.writeUTF(this.id);
        idToSend.flush();

    } catch (IOException e) {
    }
}
}

and Server:

public class Server {

private ServerSocket serverSocket;

Server(final int port) throws IOException {
    serverSocket = new ServerSocket(port);
}

void receiveData(Socket socket) {
    try (DataInputStream idStream = new DataInputStream(socket.getInputStream())) {

        String id = idStream.readUTF();
        Client client = new Client(socket, id);

    } catch (IOException e) {
    }
}
}

And the last one. You have to understand the main purpose of ServerSocket and Socket classes. In short the first waits for requests to come in over network. The second is an endpoind to the first. You won't receive socket neither standart nor custom accepting it on ServerSocket side. Instead you will establish the connection between them. There are range of stream classes to transfer data. Just use them. If you need to perform some validation, write ServerProtocol class for that purpose.

You need to override accept() to create a CustomObject with a null SocketImpl argument, and then call implAccept() with it and return it.

public Socket accept() throws IOException {
    if (isClosed())
        throw new SocketException("Socket is closed");
    if (!isBound())
        throw new SocketException("Socket is not bound yet");
    Socket s = new CustomSocket((SocketImpl) null);
    implAccept(s);
    return s;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM