java Socket 编程
Socket用于网络连接,其中封装了主机的名称,IP地址,端口号等相关信息。使用IO进行读写数据。
网络连接常用的模型
C/S模型
Client/Server 客户端对服务端
B/S模式
浏览器/服务器 一种特殊的C/S
统一了客户端:浏览器
统一了通信协议:http协议
java实现网路通信
两个重要的类
ServerSocket 服务端Socket
Socket 客户端Socket
ServerSocket运行在服务端,Socket运行在客户端。
连接步骤:
1:创建ServerSocket
2:创建客户端Socket
3:打开输入输出流
4:进行读写操作达到通信的目的
5:关闭连接
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务端
* @author Administrator
*
*/
public class Server {
//服务端Socket
private ServerSocket server;
public Server(){
//网络连接一定要捕获异常
try {
/**
* 创建服务端的时候要指定服务端口号
*/
server = new ServerSocket(8088);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 用于接收客户端的连接
*/
public void start(){
try {
/**
* 在8088端口上监听客户端的连接
* accept方法为阻塞方法,直到客户端连接才会返回
* 返回的就是封装了客户端信息的Socket
*/
while(true){
System.out.println("等待客户端连接。。。");
Socket socket = server.accept();
System.out.println("一个客户端连接了!");
/**
* 当一个客户端连接上后,启动一个线程
* 并将这个Socket交给这个线程,让线程
* 循环读取这个客户端发送过来的信息并
* 输出到控制台
*/
ClientHandler handler =
new ClientHandler(socket);
Thread t = new Thread(handler);
t.start();
}
} catch (Exception e) {
}
}
public static void main(String[] args) {
//创建服务端实例
Server server = new Server();
server.start();
}
/**
* 创建一个线程类,用于接收客户端发送过来的信息
*/
public class ClientHandler implements Runnable{
/**
* 当前线程处理的客户端的Socket
*/
private Socket client;
public ClientHandler(Socket client){
this.client = client;
}
public void run(){
try{
//获取客户端的输入流,用于读取客户端发送过来的信息
InputStream in = client.getInputStream();
//包装为用于读取字符串的缓冲字符输入流
BufferedReader reader =
new BufferedReader(
new InputStreamReader(
in
)
);
String str = null;
while(true){
str = reader.readLine();
System.out.println("客户端说:"+str);
}
}catch(Exception e){
}
}
}
}
MINA框架
Socket的开源框架
中国很多流行的游戏后台服务器都使用它
当用户频繁的登录和登出,我们的服务端就会频繁的创建线程和销毁线程。这样做会给服务器带来不少不必要的开销。为了解决频繁创建和销毁线程,让线程能够得到最大程度的重用,java提供了一个技术,线程池。
线程池的实现原理:
首先创建一些空的线程(不执行任何任务),当有一个任务时(Runnable),则取出一个线程来运行这个任务,当任务运行完毕后,不销毁线程,而是回收线程等待下次使用。
java中线程池类
ExecutorService
用于管理线程池的启动,终止等操作。
创建线程池
Executors用来创建不同类型的线程池
1:
Executors.newCachedThreadPool()
创建一个根据需要创建新线程的线程池,在这些线程空闲时可以重用他们。
2:
Executors.newFixedThreadPool(int size)
创建一个指定大小的线程池,当线程空闲时可以重用。
3:
Executors.new ScheduledThreadPool(int)
可以将任务指定一个延迟时间,在延迟时间过后再执行任务的固定大小的线程池
4:
Executors.newSingleThreadExecutor()
只有一个线程,当线程处于运行状态时,其他任务都需要等待。
多线程使用队列时,因为要考虑线程安全问题,所以我们必须要做的事情是将添加元素和获取元素的操作同步,就是多线程不能同时存取元素。在高并发情况下,这样的效率比较低。
双缓冲队列
内部维护两个队列,这样做可以实现同一时刻一个线程存(offer),另一个线程取(poll)。
原理是
A线程存元素时,向A队列添加,B线程取元素时从B队列取,当两个操作完成后,交换。
使用双缓冲队列,起码可以实现同时进行存取工作,但是,还是不能同时存或同时取。
BlockingDeque双缓冲队列
1:ArrayBlockingDeque:规定大小的 BlockingDeque,构造方法含有一个int型参数
用于指定队列大小。队列存取本着FIFO( 先进先出 First Input First Output)
当队列元素满了时,新添加元素则进行排队 等待,offer有个重载方法, 允许设置超时 时间,超时时间过后还没能添加则放弃,打 断等待会抛出异常。
2:LinkedBlockingDeque:不定长队列,可根据 需要添加元素。该队列允许的最大值为 Integer.MAX_VALUE。
LinkedBlockingDeque也支持有int参数的构 造方法,可以指定队列大小。
存取数据本着先入先出原则(FIFO)
3:PriorityBlockDeque:和 LinkedBlockingDeque一样,但是存去元素 本着自然排序原则。同样的,该队列有一个 重载的构造方法,允许我们传入一 Comparator,按照我们指定的比较规则进 行排序
4: SynchronousQueue:一个比较特殊的 BlockingDeque,存取元素必须同步,存一 次取一次。交替进行。