- tcp/ip其实是一个协议族,不是具体的某个协议
- tcp协议是属于tcp/ip协议族中的一个具体的协议
下面来介绍一下Tcp协议的Socket通信(服务端)的四种情况
第一种
/**
- Socket的服务端
当前程序有弊端 只能为1个客户端提供服务
*
/
public class MyServerSocket01 {
/
* 程序的执行入口
*
* @param args 传递的参数
*/
public static void main(String[] args) throws Exception {
//创建服务端的Socket对象
ServerSocket serverSocket = new ServerSocket();
//服务端绑定端口
serverSocket.bind(new InetSocketAddress(8899));
//监听客户端的连接(阻塞的方法),返回的是当前连接到服务器的客户端的对象
Socket socket = serverSocket.accept();
System.out.println("有客户端" + socket.getRemoteSocketAddress() + "连接到服务器了.....");
InputStream inputStream = socket.getInputStream();
//读数据
byte[] buf = new byte[2];
int len;
//调用read方法返回阻塞,当没有数据时会阻塞,并不会返回-1
while ((len = inputStream.read(buf)) != -1) {
String str = new String(buf, 0, len);
System.out.println(str);
}
}
}
第二种
/**
- Socket的服务端
- 当前程序有弊端 只能为一个客户端提供服务,只不过一个客户端断开连接之后其他的客户端才能进来
/
public class MyServerSocket02 {
/*
- 程序的执行入口
- @param args 传递的参数
*/
public static void main(String[] args) throws Exception {
//创建服务端的Socket对象
ServerSocket serverSocket = new ServerSocket();
//服务端绑定端口
serverSocket.bind(new InetSocketAddress(8899));
while (true) {
//监听客户端的连接(阻塞的方法),返回的是当前连接到服务器的客户端的对象
Socket socket = serverSocket.accept();
System.out.println(“有客户端” + socket.getRemoteSocketAddress() + “连接到服务器了…”);
InputStream inputStream = socket.getInputStream();
//读数据
byte[] buf = new byte[2];
int len;
//调用read方法返回阻塞,当没有数据时会阻塞,并不会返回-1
while ((len = inputStream.read(buf)) != -1) {
String str = new String(buf, 0, len);
System.out.println(str);
}
}
}
}
第三种
/**
- Socket的服务端
- 当前程序有弊端 每次一个客户端进来之后都会创建一个线程去处理连接任务,但有大量的客户端连接到服务器的话就会有大量的线程创建,线程的创建和上下文的切换也是非常耗费时间和资源的
/
public class MyServerSocket02 {
/*
- 程序的执行入口
- @param args 传递的参数
*/
public static void main(String[] args) throws Exception {
//创建服务端的Socket对象
ServerSocket serverSocket = new ServerSocket();
//服务端绑定端口
serverSocket.bind(new InetSocketAddress(8899));
while (true) {
//监听客户端的连接(阻塞的方法),返回的是当前连接到服务器的客户端的对象
Socket socket = serverSocket.accept();
//每次有新的客户端连接到服务器之后都会启动线程来执行
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(“有客户端” + socket.getRemoteSocketAddress() + “连接到服务器了…”);
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
//读数据
byte[] buf = new byte[2];
int len;
//调用read方法返回阻塞,当没有数据时会阻塞,并不会返回-1
while ((len = inputStream.read(buf)) != -1) {
String str = new String(buf, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
第四种
/**
- Socket的服务端
- 当前程序有弊端 有两个阻塞 accept read,其中accept我们就无法解决,但是read阻塞可以解决的(NIO)
/
public class MyServerSocket04 {
/*
- 程序的执行入口
- @param args 传递的参数
*/
public static void main(String[] args) throws Exception {
//创建线程池对象(线程池的大小是本机的cpu可用的核数)
ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
//创建服务端的Socket对象
ServerSocket serverSocket = new ServerSocket();
//服务端绑定端口
serverSocket.bind(new InetSocketAddress(8899));
while (true) {
//监听客户端的连接(阻塞的方法),返回的是当前连接到服务器的客户端的对象
Socket socket = serverSocket.accept();
//每次有新的客户端连接到服务器之后都会启动线程来执行
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("有客户端" + socket.getRemoteSocketAddress() + "连接到服务器了.....");
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
//读数据
byte[] buf = new byte[2];
int len;
//调用read方法返回阻塞,当没有数据时会阻塞,并不会返回-1
while ((len = inputStream.read(buf)) != -1) {
String str = new String(buf, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
}