java学习小笔记(三.socket通信)【转】
三,socket通信
1.http://blog.csdn.net/kongxx/article/details/7288896这个人写的关于socket通信不错,循序渐进式的讲解,用代码示例说明,运用流和socket进行远程通讯
2.最简单的socket是一个服务端对应一个客户端
server的写法
- ServerSocket server = new ServerSocket(10000);
- Socket socket = server.accept();
- BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
- PrintWriter out = new PrintWriter(socket.getOutputStream());
- while (true) {
- String msg = in.readLine();
- System.out.println(msg);
- out.println("Server received " + msg);
- out.flush();
- if (msg.equals("bye")) {
- break;
- }
- }
- socket.close();
client的写法
- Socket socket = new Socket("localhost", 10000);
- BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
- PrintWriter out = new PrintWriter(socket.getOutputStream());
- BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
- while (true) {
- String msg = reader.readLine();
- out.println(msg);
- out.flush();
- if (msg.equals("bye")) {
- break;
- }
- System.out.println(in.readLine());
- }
- socket.close();
3.复杂一点的就是多个客户端同时访问服务器。在客户端使用循环启动多个客户端访问同一服务端,在服务端只要server.accept()一接收到就新建线程,然后把把上面的读写操作放进线程内处理。
4.如果要利用socke传递对象,就要让对象实现Serializable 序列化接口,使用ObjectInputStream和ObjectOutputStream进行序列化和反序列化
server的写法
- ObjectInputStream is = null;
- ObjectOutputStream os = null;
- try {
- is = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
- os = new ObjectOutputStream(socket.getOutputStream());
- Object obj = is.readObject();
- User user = (User)obj;
- System.out.println("user: " + user.getName() + "/" + user.getPassword());
- user.setName(user.getName() + "_new");
- user.setPassword(user.getPassword() + "_new");
- os.writeObject(user);
- os.flush();
- } catch (IOException ex) {
- ObjectOutputStream os = null;
- ObjectInputStream is = null;
- try {
- socket = new Socket("localhost", 10000);
- os = new ObjectOutputStream(socket.getOutputStream());
- User user = new User("user_" + i, "password_" + i);
- os.writeObject(user);
- os.flush();
- is = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
- Object obj = is.readObject();
- if (obj != null) {
- user = (User)obj;
- System.out.println("user: " + user.getName() + "/" + user.getPassword());
- }
- } catch(IOException ex) {
5.如果还需要传送时压缩流再传送,就要用到GZIPInputStream和GZIPOutputStream进行压缩和反压缩
server的写法
- GZIPInputStream gzipis = null;
- ObjectInputStream ois = null;
- GZIPOutputStream gzipos = null;
- ObjectOutputStream oos = null;
- try {
- gzipis = new GZIPInputStream(socket.getInputStream());
- ois = new ObjectInputStream(gzipis);
- gzipos = new GZIPOutputStream(socket.getOutputStream());
- oos = new ObjectOutputStream(gzipos);
- Object obj = ois.readObject();
- User user = (User)obj;
- System.out.println("user: " + user.getName() + "/" + user.getPassword());
- user.setName(user.getName() + "_new");
- user.setPassword(user.getPassword() + "_new");
- oos.writeObject(user);
- oos.flush();
- gzipos.finish();
- } catch (IOException ex) {
- Socket socket = null;
- GZIPOutputStream gzipos = null;
- ObjectOutputStream oos = null;
- GZIPInputStream gzipis = null;
- ObjectInputStream ois = null;
- try {
- socket = new Socket();
- SocketAddress socketAddress = new InetSocketAddress("localhost", 10000);
- socket.connect(socketAddress, 10 * 1000);
- socket.setSoTimeout(10 * 1000);
- gzipos = new GZIPOutputStream(socket.getOutputStream());
- oos = new ObjectOutputStream(gzipos);
- User user = new User("user_" + i, "password_" + i);
- oos.writeObject(user);
- oos.flush();
- gzipos.finish();
- gzipis = new GZIPInputStream(socket.getInputStream());
- ois = new ObjectInputStream(gzipis);
- Object obj = ois.readObject();
- if (obj != null) {
- user = (User)obj;
- System.out.println("user: " + user.getName() + "/" + user.getPassword());
- }
- } catch(IOException ex) {
6.如果要加密传送,就要使用加密后的socket,而不是使用加密的流
server的写法,只需要对socket进行处理,流的处理不变
- ServerSocketFactory factory = SSLServerSocketFactory.getDefault();
- ServerSocket server = factory.createServerSocket(10000);
client的写法
- SocketFactory factory = SSLSocketFactory.getDefault();
- socket = factory.createSocket("localhost", 10000);
keytool -genkey -alias mysocket -keyalg RSA -keystore mysocket.jks
7.使用nio实现socket通信
client的写法
上面的例子都需要先运行server再运行client。
7.使用nio实现socket通信
java.nio包是Java在1.4之后增加的,用来提高I/O操作的效率。在nio包中主要包括以下几个类或接口:
* Buffer:缓冲区,用来临时存放输入或输出数据。
* Charset:用来把Unicode字符编码和其它字符编码互转。
* Channel:数据传输通道,用来把Buffer中的数据写入到数据源,或者把数据源中的数据读入到Buffer。
* Selector:用来支持异步I/O操作,也叫非阻塞I/O操作。
把对象转为字节数组- public static byte[] toBytes(Object object) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = null;
- try {
- oos = new ObjectOutputStream(baos);
- oos.writeObject(object);
- byte[] bytes = baos.toByteArray();
- return bytes;
- ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- ObjectInputStream ois = null;
- try {
- ois = new ObjectInputStream(bais);
- Object object = ois.readObject();
- return object;
- Selector selector = null;
- ServerSocketChannel serverSocketChannel = null;
- try {
- selector = Selector.open();
- serverSocketChannel = ServerSocketChannel.open();
- serverSocketChannel.configureBlocking(false);
- serverSocketChannel.socket().setReuseAddress(true);
- serverSocketChannel.socket().bind(new InetSocketAddress(10000));
- serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
- while (selector.select() > 0) {
- Iterator<SelectionKey> it = selector.selectedKeys().iterator();
- while (it.hasNext()) {
- SelectionKey readyKey = it.next();
- it.remove();
- execute((ServerSocketChannel) readyKey.channel());
- private static void execute(ServerSocketChannel serverSocketChannel) throws IOException {
- SocketChannel socketChannel = null;
- try {
- socketChannel = serverSocketChannel.accept();
- MyRequestObject myRequestObject = receiveData(socketChannel);
- logger.log(Level.INFO, myRequestObject.toString());
- MyResponseObject myResponseObject = new MyResponseObject(
- "response for " + myRequestObject.getName(),
- "response for " + myRequestObject.getValue());
- sendData(socketChannel, myResponseObject);
- MyRequestObject myRequestObject = null;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ByteBuffer buffer = ByteBuffer.allocate(1024);
- try {
- byte[] bytes;
- int size = 0;
- while ((size = socketChannel.read(buffer)) >= 0) {
- buffer.flip();
- bytes = new byte[size];
- buffer.get(bytes);
- baos.write(bytes);
- buffer.clear();
- }
- bytes = baos.toByteArray();
- Object obj = SerializableUtil.toObject(bytes);
- myRequestObject = (MyRequestObject)obj;
- sendData(SocketChannel socketChannel, MyResponseObject myResponseObject) throws IOException {
- byte[] bytes = SerializableUtil.toBytes(myResponseObject);
- ByteBuffer buffer = ByteBuffer.wrap(bytes);
- socketChannel.write(buffer);
client的写法
- socketChannel = SocketChannel.open();
- SocketAddress socketAddress = new InetSocketAddress("localhost", 10000);
- socketChannel.connect(socketAddress);
- MyRequestObject myRequestObject = new MyRequestObject("request_" + idx, "request_" + idx);
- logger.log(Level.INFO, myRequestObject.toString());
- sendData(socketChannel, myRequestObject);
- MyResponseObject myResponseObject = receiveData(socketChannel);
- logger.log(Level.INFO, myResponseObject.toString());
- private void sendData(SocketChannel socketChannel, MyRequestObject myRequestObject) throws IOException {
- byte[] bytes = SerializableUtil.toBytes(myRequestObject);
- ByteBuffer buffer = ByteBuffer.wrap(bytes);
- socketChannel.write(buffer);
- socketChannel.socket().shutdownOutput();
- private MyResponseObject receiveData(SocketChannel socketChannel) throws IOException {
- MyResponseObject myResponseObject = null;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try {
- ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
- byte[] bytes;
- int count = 0;
- while ((count = socketChannel.read(buffer)) >= 0) {
- buffer.flip();
- bytes = new byte[count];
- buffer.get(bytes);
- baos.write(bytes);
- buffer.clear();
- }
- bytes = baos.toByteArray();
- Object obj = SerializableUtil.toObject(bytes);
- myResponseObject = (MyResponseObject) obj;
- socketChannel.socket().shutdownInput();
上面的例子都需要先运行server再运行client。