Implement socket API

This commit is contained in:
Ilya Mizus
2013-11-05 00:07:43 +03:00
committed by Joshua Warner
parent 2800ffe826
commit 45ee25f68c
10 changed files with 623 additions and 56 deletions

View File

@ -10,10 +10,191 @@
package java.net;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public abstract class Socket {
public static native void init() throws IOException;
public class Socket implements Closeable, AutoCloseable {
public abstract void setTcpNoDelay(boolean on) throws SocketException;
private static final int SD_RECEIVE = 0x00;
private static final int SD_SEND = 0x01;
private static final int SD_BOTH = 0x02;
private static final int BUFFER_SIZE = 65535;
/**
* This method is called from all routines that depend on winsock in windows,
* so it has public visibility
* @throws IOException
*/
public static native void init() throws IOException;
/**
* Creates the native socket object
* @return Handle to the native object
* @throws IOException
*/
private static native /* SOCKET */long create() throws IOException;
/**
* Connects the native socket object to an address:port
* @param sock Native socket handler
* @param addr Address to connect to
* @param port Port to connect to
* @throws IOException
*/
private static native void connect(/* SOCKET */long sock, long addr, short port) throws IOException;
private static native void bind(/* SOCKET */long sock, long addr, short port) throws IOException;
private static native void send(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException;
private static native int recv(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException;
private static native void abort(/* SOCKET */long sock);
private static native void close(/* SOCKET */long sock);
private static native void closeOutput(/* SOCKET */long sock);
private static native void closeInput(/* SOCKET */long sock);
private class SocketInputStream extends InputStream {
private boolean closed = false;
@Override
public void close() throws IOException {
if (!closed) {
closeInput(sock);
closed = true;
}
super.close();
}
@Override
protected void finalize() throws Throwable {
close();
super.finalize();
}
@Override
public int read() throws IOException {
byte[] buffer = new byte[1];
int size = recv(sock, buffer, 0, 1);
if (size == 0) {
return -1;
}
return buffer[0];
}
@Override
public int read(byte[] buffer) throws IOException {
int fullSize = buffer.length;
int index = 0;
int size;
do {
size = recv(sock, buffer, index, Math.min(fullSize, Socket.BUFFER_SIZE));
fullSize -= size;
index += size;
} while (fullSize != 0 && size != 0);
return index;
}
}
private class SocketOutputStream extends OutputStream {
private boolean closed = false;
@Override
public void close() throws IOException {
if (!closed) {
closeOutput(sock);
closed = true;
}
super.close();
}
@Override
protected void finalize() throws Throwable {
close();
super.finalize();
}
@Override
public void write(int c) throws IOException {
byte[] res = new byte[1];
res[0] = (byte)c;
send(sock, res, 0, 1);
}
@Override
public void write(byte[] buffer) throws IOException {
int fullSize = buffer.length;
int index = 0;
int size;
do {
size = Math.min(fullSize, Socket.BUFFER_SIZE);
send(sock, buffer, index, size);
fullSize -= size;
index += size;
} while (fullSize != 0 && size != 0);
}
}
private long sock;
private SocketInputStream inputStream;
private SocketOutputStream outputStream;
public Socket() throws IOException {
Socket.init();
sock = create();
inputStream = new SocketInputStream();
outputStream = new SocketOutputStream();
}
public SocketInputStream getInputStream() {
return inputStream;
}
public SocketOutputStream getOutputStream() {
return outputStream;
}
public Socket(InetAddress address, int port) throws IOException {
this();
connect(sock, address.getRawAddress(), (short)port);
}
public Socket(String host, int port) throws UnknownHostException, IOException {
this(InetAddress.getByName(host), port);
}
public void bind(SocketAddress bindpoint) throws IOException {
if (bindpoint instanceof InetSocketAddress) {
InetSocketAddress inetBindpoint = (InetSocketAddress)bindpoint;
bind(sock, inetBindpoint.getAddress().getRawAddress(), (short) inetBindpoint.getPort());
}
}
public void setTcpNoDelay(boolean on) throws SocketException {}
@Override
public void close() throws IOException {
close(sock);
}
public void shutdownInput() throws IOException {
inputStream.close();
}
public void shutdownOutput() throws IOException {
outputStream.close();
}
@Override
protected void finalize() throws Throwable {
close();
super.finalize();
}
}