package com.bowei.socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* @Description:
* @Auther:
* @Date: 2019/12/20 16:41
* @version:
*/
public class SocketClient {
public static void main(String[] args) throws Exception {
demo2();
}
// 双向通信 发送--> 接受
public static void demo2()throws Exception {
// 要连接的服务端IP地址和端口
String host = "127.0.0.1";
int port = 55533;
// 与服务端建立连接
Socket socket = new Socket(host, port);
// 建立连接后获得输出流
OutputStream outputStream = socket.getOutputStream();
String message="你好 yiwangzhibujian";
socket.getOutputStream().write(message.getBytes("UTF-8"));
//发送数据完成 后续只能接受数据
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream();
byte [] bytes= new byte[1024];
StringBuilder sb= new StringBuilder();
int len;
while ((len=inputStream.read(bytes))!=-1){
//注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
sb.append(new String(bytes, 0, len,"UTF-8"));
}
System.out.println("get message from client: " + sb);
inputStream.close();
outputStream.close();
socket.close();
}
// 最基础的简单的通信形式
public static void demo1()throws Exception {
// 要连接的服务端IP地址和端口
String host = "127.0.0.1";
int port = 55533;
// 与服务端建立连接
Socket socket = new Socket(host, port);
// 建立连接后获得输出流
OutputStream outputStream = socket.getOutputStream();
String message="你好 yiwangzhibujian";
socket.getOutputStream().write(message.getBytes("UTF-8"));
outputStream.close();
socket.close();
}
}
package com.bowei.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @Description:
* @Auther: shanshaowei
* @Date: 2019/12/20 16:40
* @version:
*/
public class SocketServer {
public static void main(String[] args) throws Exception {
demo3();
}
//多线程处理socket 每个socket 需要用一个线程来处理 伪异步
public static void demo3()throws Exception{
// 监听指定的端口
int port = 55533;
ServerSocket server = new ServerSocket(port);
// server将一直等待连接的到来
System.out.println("server将一直等待连接的到来");
ExecutorService executorService = Executors.newCachedThreadPool();
while (true){
Socket socket = server.accept();
Runnable runnable=()->{
try{
// 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(bytes)) != -1) {
//注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
sb.append(new String(bytes, 0, len,"UTF-8"));
}
System.out.println("get message from client: " + sb);
// 接受到消息 给客户端返回
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello Client,I get the message.".getBytes("UTF-8"));
outputStream.close();
inputStream.close();
socket.close();
server.close();
}catch (Exception e){
e.printStackTrace();
}
};
executorService.submit(runnable);
}
}
// 双向通信 接受-->发送
public static void demo2() throws Exception{
// 监听指定的端口
int port = 55533;
ServerSocket server = new ServerSocket(port);
// server将一直等待连接的到来
System.out.println("server将一直等待连接的到来");
Socket socket = server.accept();
// 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(bytes)) != -1) {
//注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
sb.append(new String(bytes, 0, len,"UTF-8"));
}
System.out.println("get message from client: " + sb);
// 接受到消息 给客户端返回
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello Client,I get the message.".getBytes("UTF-8"));
outputStream.close();
inputStream.close();
socket.close();
server.close();
}
// 单向通信
public static void demo1()throws IOException{
// 监听指定的端口
int port = 55533;
ServerSocket server = new ServerSocket(port);
// server将一直等待连接的到来
System.out.println("server将一直等待连接的到来");
Socket socket = server.accept();
// 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(bytes)) != -1) {
//注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8
sb.append(new String(bytes, 0, len,"UTF-8"));
}
System.out.println("get message from client: " + sb);
inputStream.close();
socket.close();
server.close();
}
}
使用NIO的形式实现网络的通信
package com.bowei.socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
/**
* @Description:
* @Auther: shanshaowei
* @Date: 2019/12/24 08:58
* @version:
*/
public class NioSocketClient {
public void start() {
// 打开通道
try (SocketChannel socketChannel = SocketChannel.open()) {
//连接服务端socket
SocketAddress socketAddress = new InetSocketAddress("localhost", 8888);
//连接服务端
socketChannel.connect(socketAddress);
int sendCount = 0;
// 设定缓存区的大小
ByteBuffer buffer = ByteBuffer.allocate(1024);
//这里最好使用selector处理 这里只是为了写的简单
while (sendCount < 10) {
buffer.clear();
//向服务端发送消息
buffer.put(("current time : " + System.currentTimeMillis()).getBytes());
//读取模式
buffer.flip();
socketChannel.write(buffer);
buffer.clear();
//从服务端读取消息
int readLenth = socketChannel.read(buffer);
//读取模式
buffer.flip();
byte[] bytes = new byte[readLenth];
buffer.get(bytes);
System.out.println(new String(bytes, "UTF-8"));
buffer.clear();
sendCount++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new NioSocketClient().start();
}
}
package com.bowei.socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
/**
* @Description:
* @Auther: shanshaowei
* @Date: 2019/12/23 17:58
* @version:
*
*
*
*/
public class NioSocketServer {
private volatile byte flag = 1;
public void setFlag(byte flag) {
this.flag = flag;
}
public void start() {
//创建serverSocketChannel,监听8888端口
try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {
serverSocketChannel.socket().bind(new InetSocketAddress(8888));
//设置为非阻塞模式
serverSocketChannel.configureBlocking(false);
//为serverChannel注册selector
Selector selector = Selector.open();
// 注册到selector
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务端开始工作:");
//创建消息处理器
ServerHandlerBs handler = new ServerHandlerImpl(1024);
while (flag == 1) {
selector.select();
System.out.println("开始处理请求 : ");
//获取selectionKeys并处理
Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
try {
//连接请求
if (key.isAcceptable()) {
// 处理这个 key-> channel
handler.handleAccept(key);
}
//读请求
if (key.isReadable()) {
System.out.println(handler.handleRead(key));
}
} catch (IOException e) {
e.printStackTrace();
}
//处理完后移除当前使用的key
keyIterator.remove();
}
System.out.println("完成请求处理。");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
NioSocketServer server = new NioSocketServer();
new Thread(() -> {
try {
Thread.sleep(10*60*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
server.setFlag((byte) 0);
}
}).start();
server.start();
}
}
package com.bowei.socket;
import java.io.IOException;
import java.nio.channels.SelectionKey;
/**
* @Description:
* @Auther: shanshaowei
* @Date: 2019/12/23 17:52
* @version:
*/
public interface ServerHandlerBs {
void handleAccept(SelectionKey selectionKey) throws IOException;
String handleRead(SelectionKey selectionKey)throws IOException;
}
package com.bowei.socket;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
/**
* @Description:
* @Auther: shanshaowei
* @Date: 2019/12/23 17:53
* @version:
*/
public class ServerHandlerImpl implements ServerHandlerBs {
private int bufferSize = 1024;
private String localCharset = "UTF-8";
public ServerHandlerImpl() {
}
public ServerHandlerImpl(int bufferSize) {
this(bufferSize, null);
}
public ServerHandlerImpl(String localCharset) {
this(-1, localCharset);
}
public ServerHandlerImpl(int bufferSize, String localCharset) {
this.bufferSize = bufferSize > 0 ? bufferSize : this.bufferSize;
this.localCharset = localCharset == null ? this.localCharset : localCharset;
}
@Override
public void handleAccept(SelectionKey selectionKey) throws IOException {
//获取channel
SocketChannel socketChannel = ((ServerSocketChannel) selectionKey.channel()).accept();
//非阻塞
socketChannel.configureBlocking(false);
//注册selector
socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize));
System.out.println("建立请求......");
}
@Override
public String handleRead(SelectionKey selectionKey) throws IOException {
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer buffer = (ByteBuffer) selectionKey.attachment();
String receivedStr = "";
if (socketChannel.read(buffer) == -1) {
//没读到内容关闭
socketChannel.shutdownOutput();
socketChannel.shutdownInput();
socketChannel.close();
System.out.println("连接断开......");
} else {
//将channel改为读取状态
buffer.flip();
//按照编码读取数据
receivedStr = Charset.forName(localCharset).newDecoder().decode(buffer).toString();
buffer.clear();
//返回数据给客户端
buffer = buffer.put(("received string : " + receivedStr).getBytes(localCharset));
//读取模式
buffer.flip();
socketChannel.write(buffer);
//注册selector 继续读取数据
socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize));
}
return receivedStr;
}
}
使用netty实现网络通信的模型
package com.bowei.nio;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.net.InetSocketAddress;
/**
* @Description:
* @Auther: shanshaowei
* @Date: 2019/12/23 17:30
* @version:
*/
public class EchoClient {
private String host;
private int port;
public EchoClient(String host, int port) {
this.host = host;
this.port = port;
}
public void start() throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host, port))
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new EchoClientHandler());
}
});
ChannelFuture future = bootstrap.connect().sync();
future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws Exception{
new EchoClient("localhost",65535).start();
}
}
package com.bowei.nio;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;
/**
* @Description:
* @Auther: shanshaowei
* @Date: 2019/12/23 17:38
* @version:
*/
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.write(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
System.out.println("Client received: " + ByteBufUtil.hexDump(msg.readBytes(msg.readableBytes())));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
package com.bowei.nio;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* @Description:
* @Auther: shanshaowei
* @Date: 2019/12/23 17:11
* @version:
*/
public class EchoServer {
private int port;
public EchoServer(int port){
this.port=port;
}
public void start() throws Exception{
//NioEventLoopGroup 用来接收和处理新的链接
EventLoopGroup group= new NioEventLoopGroup();
try{
ServerBootstrap bootstrap= new ServerBootstrap();
//指定通道的类型 NioServerSocketChannel.class 监听的端口 port
bootstrap.group(group).channel(NioServerSocketChannel.class).localAddress(port)
.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(new EchoServerHandler());
}
});
ChannelFuture future= bootstrap.bind().sync();
System.out.println(EchoServer.class+"started and listen on"+future.channel().localAddress());
future.channel().closeFuture().sync();
}finally {
group.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws Exception{
new EchoServer(65535).start();
}
}
package com.bowei.nio;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/**
* @Description:
* @Auther: shanshaowei
* @Date: 2019/12/23 17:18
* @version:
*/
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("Server received: " + msg);
ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}