步骤
1.创建服务器端套接字对象
作用 套接字实现类:包含了创建套接字 绑定到ip端口 监听 方法
2.绑定到ip端口
作用 唯一定位到一台机器的一个进程/程序 从而实现不同机器的不同程序的互相通信/读写数据
3.监听
?连接数量还是连接超时时间?
4.接受客户端连接
阻塞 直到有客户端连接进来
应用程序
package simple;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务器端
* @author gongzhihao
*
*/
public class Server {
public static void main(String[] args) {
try {
//创建服务器端套接字
ServerSocket ss = new ServerSocket(8888);
System.out.println("启动服务器....");
//接受客户端的连接
Socket s = ss.accept(); //阻塞 直到有客户端连接进来
System.out.println("客户端:" + s.getInetAddress().getLocalHost() + "已连接到服务器");
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
// 读取客户端发送来的消息
String mess = br.readLine();
System.out.println("客户端:" + mess);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write(mess + "\n");
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
复制代码
jdk util包-socket
创建服务器端套接字对象
说明:源码基于jdk8
//服务端套接字类
public
class ServerSocket implements java.io.Closeable {
/**
* The implementation of this Socket.
*/
private SocketImpl impl; //套接字实现SocksSocketImpl
public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
setImpl(); //套接字实现
if (port < 0 || port > 0xFFFF)
throw new IllegalArgumentException(
"Port value out of range: " + port);
if (backlog < 1)
backlog = 50;
try {
bind(new InetSocketAddress(bindAddr, port), backlog);
} catch(SecurityException e) {
close();
throw e;
} catch(IOException e) {
close();
throw e;
}
}
复制代码
private void setImpl() {
if (factory != null) {
impl = factory.createSocketImpl();
checkOldImpl();
} else {
// No need to do a checkOldImpl() here, we know it's an up to date
// SocketImpl!
impl = new SocksSocketImpl(); //问题-套接字实现和ServerSocket区别?
}
if (impl != null)
impl.setServerSocket(this);
}
复制代码
//bind
public void bind(SocketAddress endpoint, int backlog) throws IOException {
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 instanceof InetSocketAddress))
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;
throw e;
} catch(IOException e) {
bound = false;
throw e;
}
}
复制代码
/**
* Get the {@code SocketImpl} attached to this socket, creating
* it if necessary.
*
* @return the {@code SocketImpl} attached to that ServerSocket.
* @throws SocketException if creation fails.
* @since 1.4
*/
SocketImpl getImpl() throws SocketException {
if (!created)
createImpl();
return impl;
}
/**
* Creates the socket implementation.
*
* @throws IOException if creation fails
* @since 1.4
*/
void createImpl() throws SocketException {
if (impl == null)
setImpl();
try {
impl.create(true);
created = true;
} catch (IOException e) {
throw new SocketException(e.getMessage());
}
}
复制代码
//套接字实现
/* whether this Socket is a stream (TCP) socket or not (UDP)
*/
protected boolean stream; //问题-tcp utp的区别?
/**
* The file descriptor object for this socket.
*/
protected FileDescriptor fd; //问题-套接字的文件描述符对象?
/**
* Default Socket Implementation. This implementation does
* not implement any security checks.
* Note this class should <b>NOT</b> be public.
*
* @author Steven B. Byrne
*/
abstract class AbstractPlainSocketImpl extends SocketImpl
{
/**
* Creates a socket with a boolean that specifies whether this
* is a stream socket (true) or an unconnected UDP socket (false).
*/
protected synchronized void create(boolean stream) throws IOException {
this.stream = stream; //是tcp还是udp?
if (!stream) {
ResourceManager.beforeUdpCreate();
// only create the fd after we know we will be able to create the socket
fd = new FileDescriptor(); //套接字的文件描述符?
try {
socketCreate(false); //创建套接字 //没有找到这个方法的最终实现类?
} catch (IOException ioe) {
ResourceManager.afterUdpClose();
fd = null;
throw ioe;
}
} else {
fd = new FileDescriptor();
socketCreate(true);
}
if (socket != null)
socket.setCreated();
if (serverSocket != null)
serverSocket.setCreated();
}
复制代码
//jdk7 //这里的代码是jdk7 上面的代码都是jdk8
class PlainSocketImpl extends AbstractPlainSocketImpl
{
native void socketCreate(boolean isServer) throws IOException; //本地方法
复制代码
注意:jdk7也是native方法 但是jdk的native方法没有native关键字
绑定到ip 端口
说明:源码基于jdk7
//ServerSocket
public void bind(SocketAddress endpoint, int backlog) throws IOException {
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 instanceof InetSocketAddress))
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;
throw e;
} catch(IOException e) {
bound = false;
throw e;
}
}
复制代码
//AbstractPlainSocketImpl
/**
* Binds the socket to the specified address of the specified local port.
* @param address the address
* @param port the port
*/
protected synchronized void bind(InetAddress address, int lport)
throws IOException
{
synchronized (fdLock) {
if (!closePending && (socket == null || !socket.isBound())) {
NetHooks.beforeTcpBind(fd, address, lport);
}
}
socketBind(address, lport);
if (socket != null)
socket.setBound();
if (serverSocket != null)
serverSocket.setBound();
}
复制代码
//PlainSocketImpl
native void socketBind(InetAddress address, int port)
throws IOException; //本地方法
复制代码
监听
流程和绑定一样
/**
* Listens, for a specified amount of time, for connections.
* @param count the amount of time to listen for connections
*/
protected synchronized void listen(int count) throws IOException {
socketListen(count); //问题-?
}
复制代码
native void socketListen(int count) throws IOException;
复制代码
backlog?默认值是50