JAVA Socket模拟简单的通讯(代码实例),javasocket
依旧使用bio流。
使用线程池技术,管理服务器线程。
实现服务器关机处理,解决大部分异常处理。
package xin.tomdonkey.net.bio;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Server
{
/**
* 循环标记,是否执行接受新连接的标记
* 仅标记是否接受新连接,不标记其他状态
*/
private int port;
private boolean life;
private ServerSocket serverSocket ;
private ExecutorService threadPool = Executors.newCachedThreadPool();
public void startup()
{
while (life)
{
try
{
Socket socket = serverSocket.accept();
threadPool.submit(new ServerClient(socket));
System.out.println("一个新任务进入线程池");
System.out.println("当前线程池为:" + threadPool);
}
catch (IOException e)
{
System.err.println("serverSocket被关闭了,主循环解除阻塞");
}
}
}
public void shutDown()
{
life = false;
System.err.println("主循环退出");
try
{
serverSocket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
shutdownAndAwaitTermination(threadPool);
System.err.println("系统正常退出");
}
/**
* 此方法一定无法终止此程序下正在运行的线程,
* 此方法只能让能响应interrupt的线程终止
* 而此程序下使用的是bio,并不会抛出interrupt
* 故而只会等待线程10s执行时间,为执行完成,直接终止程序。
* @param pool
*/
private void shutdownAndAwaitTermination(ExecutorService pool)
{
pool.shutdown();
try
{
if (!pool.awaitTermination(5, TimeUnit.SECONDS))
{
pool.shutdownNow();
if (!pool.awaitTermination(5, TimeUnit.SECONDS))
{
System.err.println("线程池中存在无法被关闭的线程...");
System.err.println("系统强制关闭...");
System.exit(-1);
}
}
}
catch (InterruptedException ie)
{
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
/**
* 采用默认端口6655创建服务器
*
* @throws IOException
*/
public Server() throws IOException
{
this(6655);
}
/**
* 指定端口port创建服务器
*
* @param port 服务器监听的端口
* @throws IOException
*/
public Server(int port) throws IOException
{
this.port = port;
this.life = true;
this.serverSocket = new ServerSocket(port);
}
public static void main(String[] args) throws IOException
{
Server server = new Server();
new Thread(()->{
try
{
Thread.sleep(20000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
server.shutDown();
}).start();
server.startup();
}
}
package xin.tomdonkey.net.bio;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Random;
public class ServerClient implements Runnable
{
private boolean flag;
private InputStream inputStream ;
private OutputStream outputStream ;
public ServerClient(Socket socket)
{
flag = true;
try
{
this.inputStream = socket.getInputStream();
this.outputStream = socket.getOutputStream();
}
catch (IOException e)
{
flag = false;
System.err.println("服务器获取输入输出流时,socket出现异常,run方法将执行空语句,直接退出线程");
}
}
@Override
public void run()
{
while (flag)
{
try
{
//线程启动,即阻塞,直到客户端发出数据
//可以做一个优化,收不到数据即销毁当前线程以及链接和流
int r= inputStream.read();
System.out.println("服务器收到:" + r);
//收到后即回复给客户端一个随机值
byte b = (byte)new Random().nextInt(100);
outputStream.write(b);
System.out.println("服务器写出:" + b);
System.out.println("完成一次回复\n");
}
catch (IOException e)
{
//客户端掉线了,或者IO出现问题抛出此异常,让此线程运行终止
System.out.println("由于客户端发生异常,关闭此服务线程");
flag = false;
}
}
}
}
package xin.tomdonkey.net.bio;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Random;
public class Client
{
Socket socket ;
boolean flag = false;
InputStream inputStream ;
OutputStream outputStream ;
public Client(String address,int port) throws IOException
{
this.socket = new Socket(address,port);
this.inputStream = socket.getInputStream();
this.outputStream = socket.getOutputStream();
}
public void startup() throws IOException, InterruptedException
{
flag = true;
while (flag)
{
//由客户端发起,向服务器写出数据,一个随机byte值
byte b = (byte)new Random().nextInt(100);
outputStream.write(b);
System.out.println("写出:" + b);
//写出完成之后,线程阻塞,直到收到服务器发来的值为止
int r = inputStream.read();
System.out.println("收到:" + r);
System.out.println("完成一次请求\n");
//收到之后线程休眠2s,再向服务器写出数据
Thread.sleep(2000);
}
}
public static void main(String[] args) throws IOException, InterruptedException
{
Client client = new Client("127.0.0.1",6655);
client.startup();
}
}