简单socket和流分析__两人的聊天室

前景

由于最近有一个课设里面我是负责socket+JDBC的,所以就来学学java的socket,顺便熟悉几种流,由于我之前的进度还在数据结构红黑树和JVM那,所以先跳过来看看

socket基础

由于socket通信不难的,就直接编程了,首先是基于最简单InputStream,outputStream,字节流

服务器:

package byteserver;

import java.io.*;
import java.net.*;

public class Server 
{
    public void server()
    {
        try
        {
            ServerSocket server = new ServerSocket(55000);
            Socket socket = server.accept();

            try
            {
                // 从socket中获得输入输出流
                InputStream in = socket.getInputStream();
                OutputStream out = socket.getOutputStream();

                // 输入流读进byte数组里面
                byte[] bytes = new byte[1024];
                in.read(bytes);
                System.out.println("message from client"+new String(bytes));
            }
            finally
            {
                socket.close();
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        Server server = new Server();
        server.server();
    }
}

客户端

package byteclient;

import java.io.*;
import java.net.*;
import java.lang.StringBuilder;

public class Clinet 
{
    public void client()
    {
        try
        {
            Socket socket = new Socket("127.0.0.1",55000);

            try
            {
                OutputStream out = socket.getOutputStream();
                InputStream in = socket.getInputStream();
                out.write("Hello, this is client".getBytes());
                out.flush();
            }
            finally
            {
                socket.close();
            }
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        Clinet client = new Clinet();
        client.client();
    }
}

这是最简单的例子,做的事情也很少,仅仅是客户端发,服务端收信息

客户端发送完,服务器响应消息

客户端发送完了自己的信息之后,关闭输出流,等待服务器的回应信息,之后再关闭连接

服务器

package byteserver;

import java.io.*;
import java.net.*;

public class Server 
{
    public void server()
    {
        try
        {
            ServerSocket server = new ServerSocket(55000);
            Socket socket = server.accept();

            try
            {
                // 从socket中获得输入输出流
                InputStream in = socket.getInputStream();
                OutputStream out = socket.getOutputStream();

                // 输入流读进byte数组里面
                byte[] bytes = new byte[1024];
                in.read(bytes);
                System.out.println("message from client"+new String(bytes));

                // 服务器返回成功消息
                out.write("from server:success".getBytes());
                out.flush();
            }
            finally
            {
                socket.close();
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        Server server = new Server();
        server.server();
    }
}

客户机

package byteclient;

import java.io.*;
import java.net.*;
import java.lang.StringBuilder;

public class Clinet 
{
    public void client()
    {
        try
        {
            Socket socket = new Socket("127.0.0.1",55000);

            try
            {
                OutputStream out = socket.getOutputStream();
                InputStream in = socket.getInputStream();
                out.write("Hello, this is client".getBytes());
                out.flush();
                // 客户端发送完了,关闭输出流
                socket.shutdownOutput();

                byte[] bytes = new byte[1024];
                StringBuilder builder = new StringBuilder();
                in.read(bytes);
                System.out.println("message from server: "+new String(bytes));
            }
            finally
            {
                socket.close();
            }
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        Clinet client = new Clinet();
        client.client();
    }
}

这种半关闭的状态,HTTP的短连接和短链接很像,请求一次之后就断开,好奇HTTP的长连接怎么搞的,不过我不是网络编程,所以不去深入,主要是借助它了解流的形式的

聊天交互

刚才我们看到的都是一次性的交互,那么如果我要聊天呢?我发一句,你发一句的那种。

package client;

import java.net.Socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.Scanner;

import java.io.PrintWriter;

public class Client 
{
    public void server()
    {
        try
        {
            Socket socket = new Socket("127.0.0.1", 55000);

            try
            {
                InputStream in = socket.getInputStream();
                OutputStream out = socket.getOutputStream();
                PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, "UTF-8"),true);
                Scanner keyboard_in = new Scanner(System.in, "UTF-8");
                Scanner stream_in = new Scanner(in, "UTF-8");

                boolean flag = false;
                while(flag == false && keyboard_in.hasNextLine())
                {
                    // 键盘读取需要发送的内容
                    String keyboard_indata = keyboard_in.nextLine();
                    if (keyboard_indata.equals("end"))
                    {
                        flag = true;
                    }
                    //传递给OutputStreamWriter
                    writer.println(keyboard_indata);
                    // 输入流中接受服务器的信息
                    String indata = stream_in.nextLine();
                    System.out.println("服务器的消息:"+indata);
                }

            }
            finally
            {
                socket.close();
            }   
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        Client client = new Client();
        client.server();
    }
}

服务器

package server;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.io.IOException;


public class Server 
{
    public void service()
    {
        try
        {
            ServerSocket server = new ServerSocket(55000);
            Socket socket = server.accept();
            System.out.println(socket.getInetAddress()+"地址已经连接");
            try
            {

                OutputStream out = socket.getOutputStream();
                InputStream in = socket.getInputStream();
                PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, "UTF-8"),true);

                Scanner keyboard_in = new Scanner(System.in);
                Scanner stream_in = new Scanner(socket.getInputStream());

                while(stream_in.hasNextLine())
                {
                    String indata = stream_in.nextLine();
                    System.out.println("客户端消息:"+indata);
                    String keyboard_indata = keyboard_in.nextLine();
                    writer.println(keyboard_indata);
                }
            }
            finally
            {
                socket.close();
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        Server server = new Server();
        server.service();
    }
}

聊天倒是次要的,本文主要的是流
所有的流都有一个共同的祖先InputStream,它是一个字节流,当我们需要处理字符串和数字的时候就需要用到它的子类。

PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, "UTF-8"),true);

                Scanner keyboard_in = new Scanner(System.in);
                Scanner stream_in = new Scanner(socket.getInputStream());

PritWriter 这个类比较强大,它能基于文本的输出,以文本的格式打印字符串和数字,它的里面封装了一个OutputStreamWriter,这是一个写出器,作用是将字符流转换成字节流,意思就是说 文本->字符流->字节流,这样的一个顺序(PS,虽然PrintWriter的Print之类的方法像是打印,实际上只是输出给里面的OutputStreamWriter),最终socket发出的是还是字节流,Scanner这个类,能接收各种形式的流,所以直接包装字节流是没有问题的。

注意循环条件,服务器里面的条件是 有输入流,客户端的条件是键盘输入

总结

由于笔者只是临时学socket,所以并不深入,流也是学了一点点,日后还要系统的学习一下流的操作,今天只是做一个简单的了解

猜你喜欢

转载自blog.csdn.net/qq_41376740/article/details/80195335
今日推荐