什么是Socket?
API说:他是套接字,两台机器连接的端点。他的实际工作由SocketIml执行。
没图说个**,下面用个图能说明Socket,在哪个位置:
相关源码:
1.Socket:
属性:SocketImpl impl,socket的实现,就是API说的,实际工作由它执行。
public
class Socket implementsjava.io.Closeable {
private boolean created = false;private boolean bound = false;private boolean connected = false;private boolean closed = false;private Object closeLock = newObject();private boolean shutIn = false;private boolean shutOut = false;SocketImpl impl;
private boolean oldImpl = false;
构造方法:public Socket(String host, int port)throws UnknownHostException, IOException
创建一个socket连接到host上的port端口上。这个构造方法会调自己私有的构造方法,这个私有的方法就有设置impl.
public Socket(String host, intport)throwsUnknownHostException, IOException
{this(host != null ? newInetSocketAddress(host, port) :new InetSocketAddress(InetAddress.getByName(null), port),
(SocketAddress)null, true);
}
构造函数:private Socket(SocketAddress address, SocketAddress localAddr,boolean stream) throws IOException
这个私有的构造函数,设置iml,绑定主机,请求连接。
privateSocket(SocketAddress address, SocketAddress localAddr,boolean stream) throwsIOException {
setImpl();//backward compatibility
if (address == null)throw newNullPointerException();try{
createImpl(stream);if (localAddr != null)
bind(localAddr);
connect(address);
}catch (IOException | IllegalArgumentException |SecurityException e) {try{
close();
}catch(IOException ce) {
e.addSuppressed(ce);
}throwe;
}
}
方法: public void connect(SocketAddress endpoint, int timeout) throws IOException
用im请求连接。API说的有点道理,实际工作真是他完成的。这里用到了门面设计模式。
public void connect(SocketAddress endpoint, int timeout) throwsIOException {if (endpoint == null)throw new IllegalArgumentException("connect: The address can't be null");if (timeout < 0)throw new IllegalArgumentException("connect: timeout can't be negative");if(isClosed())throw new SocketException("Socket is closed");if (!oldImpl &&isConnected())throw new SocketException("already connected");if (!(endpoint instanceofInetSocketAddress))throw new IllegalArgumentException("Unsupported address type");
InetSocketAddress epoint=(InetSocketAddress) endpoint;
InetAddress addr=epoint.getAddress ();int port =epoint.getPort();
checkAddress(addr,"connect");
SecurityManager security=System.getSecurityManager();if (security != null) {if(epoint.isUnresolved())
security.checkConnect(epoint.getHostName(), port);elsesecurity.checkConnect(addr.getHostAddress(), port);
}if (!created)
createImpl(true);if (!oldImpl)
impl.connect(epoint, timeout);else if (timeout == 0) {if(epoint.isUnresolved())
impl.connect(addr.getHostName(), port);elseimpl.connect(addr, port);
}else
throw new UnsupportedOperationException("SocketImpl.connect(addr, timeout)");
connected= true;bound= true;
}
2.ServerSocket
属性:SocketImpl impl,实际工作也是交由他去执行。
构造方法:public ServerSocket(int port)
创建一个服务端socket,绑定到指定的端口上,具体的实现,这个构造函数调用了另一个函数去执行,这个函数将会调用绑定的方法。
public ServerSocket(int port) throwsIOException {this(port, 50, null);
}
方法:public void bind(SocketAddress endpoint, int backlog) throws IOException
用iml调用bind方法。
public void bind(SocketAddress endpoint, int backlog) throwsIOException {if(isClosed())throw new SocketException("Socket is closed");if (!oldImpl &&isBound())throw new SocketException("Already bound");if (endpoint == null)
endpoint= new InetSocketAddress(0);if (!(endpoint instanceofInetSocketAddress))throw new IllegalArgumentException("Unsupported address type");
InetSocketAddress epoint=(InetSocketAddress) endpoint;if(epoint.isUnresolved())throw new SocketException("Unresolved address");if (backlog < 1)
backlog= 50;try{
SecurityManager security=System.getSecurityManager();if (security != null)
security.checkListen(epoint.getPort());
getImpl().bind(epoint.getAddress(), epoint.getPort());
getImpl().listen(backlog);
bound= true;
}catch(SecurityException e) {
bound= false;throwe;
}catch(IOException e) {
bound= false;throwe;
}
}
方法:public Socket accept() throws IOException
监听连接,连接成功后创建一个Socket。在连接传入之前会一直阻塞.这个方法最后会调implAccept(Socket s)
public Socket accept() throwsIOException {if(isClosed())throw new SocketException("Socket is closed");if (!isBound())throw new SocketException("Socket is not bound yet");
Socket s= new Socket((SocketImpl) null);
implAccept(s);returns;
}
方法:protected final void implAccept(Socket s) throws IOException
protected final void implAccept(Socket s) throwsIOException {
SocketImpl si= null;try{if (s.impl == null)
s.setImpl();else{
s.impl.reset();
}
si=s.impl;
s.impl= null;
si.address= newInetAddress();
si.fd= newFileDescriptor();
getImpl().accept(si);
SecurityManager security=System.getSecurityManager();if (security != null) {
security.checkAccept(si.getInetAddress().getHostAddress(),
si.getPort());
}
}catch(IOException e) {if (si != null)
si.reset();
s.impl=si;throwe;
}catch(SecurityException e) {if (si != null)
si.reset();
s.impl=si;throwe;
}
s.impl=si;
s.postAccept();
}
Socket 例子
1.编写服务端代码:
importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.PrintWriter;importjava.net.ServerSocket;importjava.net.Socket;public classServer {private staticServerSocket server;public static void main(String args[]) throwsIOException {
server= new ServerSocket(9000);
Socket socket= null;
BufferedReader in= null;
PrintWriter out= null;while(true){try{
socket=server.accept();
in=new BufferedReader( newInputStreamReader(socket.getInputStream()));
out= new PrintWriter(socket.getOutputStream(),true);if(in.ready()){
System.out.println("recive data from client : "+in.readLine());
}
out.print("welcome to server.");
}catch(IOException e) {//TODO Auto-generated catch block
e.printStackTrace();
}finally{
out.close();
in.close();
}
}
}
}
2.编写客户端:
importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.PrintWriter;importjava.net.Socket;public classClient {static Socket client =null;public static voidmain(String args[]){
BufferedReader in=null;
PrintWriter out=null;try{
client= new Socket("127.0.0.1",9000);
in= new BufferedReader(newInputStreamReader(client.getInputStream()));
out= new PrintWriter(client.getOutputStream(),true);
out.println("hello server.");
System.out.println("recive data from server "+in.readLine());
}catch(IOException e) {//TODO Auto-generated catch block
e.printStackTrace();
}finally{
out.close();try{
in.close();
}catch(IOException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
运行结果:
server: recive data from client : hello server.
client:recive data from server welcome to server.



