Java TCP传输

TCP传输

Socket和ServerSocket

  • 建立客户端和服务器端
  • 建立连接后,通过Socket中的IO流进行数据的传输
  • 关闭socket
    同样,客户端与服务器端是两个独立的应用程序。

1.TCP分客户端和服务端。

2.客户端对应的对象是Socket。服务端对应的对象是ServerSocket。

客户端

通过查阅sockent对象,发现在该独享建立时,就可以去链接指定主机。因为tcp是面向连接的。所以在建立socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。

需求:给服务端发送一个文本数据。
步骤:

  • 1.创建Socket服务,并指定要连接的主机和端口。
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

class TcpClient
{
    public static void main(String[] args) throws IOException
    {
        //创建客户端的socket服务,指定目的主机和端口
        Socket s = new Socket("192.168.1.101",10003);
        //为了发送数据,应该获取socket流中的输出流。
        OutputStream out = s.getOutputStream();

        out.write("tcp ge men lai le".getBytes());
        s.close();
    }
}
class TcpServer
{
    public static void main(String[] args) throws Exception
    {
        //建立服务端socket服务。并监听一个端口
        ServerSocket ss = new ServerSocket(10003);
        //通过accept方法获取连接过来的客户端对象。
        Socket s = ss.accept();

        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+"......connected");
        //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。
        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(new String(buf,0,len));
        s.close();//关闭客户端

    }
}
7.gif

需求:定义端点接收数据并打印在控制台上。
服务端:

  • 1.建立服务端的socket服务。ServerSocket();并监听一个端口。
  • 2.获取连接过来的客户端对象。通过ServerSocket的accept方法。没有连接就会等,所以这个方法阻塞式的。
  • 3.客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。并打印在控制台。
  • 4.关闭服务端。(可选)

客户端

  • 1.建立socket服务。指定要连接主机和端口。
  • 2.获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端。
  • 3.获取socket流中的输入流,将服务端反馈的数据获取到,并打印。
  • 4.关闭客户端资源。
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

class TcpClient0
{
    public static void main(String[] args) throws Exception
    {
        Socket s = new Socket("192.168.22.38",10004);

        OutputStream out = s.getOutputStream();

        out.write("服务端,你好".getBytes());

        InputStream in = s.getInputStream();

        byte[] buf = new byte[1024];

        int len = in.read(buf);

        System.out.println(new String(buf,0,len));

        s.close();
    }
}
class TcpServer0
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10004);

        Socket s = ss.accept();

        String ip = s.getInetAddress().getHostAddress();

        System.out.println(ip+".....connected");

        InputStream in = s.getInputStream();

        byte[] buf = new byte[1024];

        int len = in.read(buf);

        System.out.println(new String(buf,0,len));

        OutputStream out = s.getOutputStream();

        out.write("哥们收到,你也好".getBytes());

        s.close();

        ss.close();
    }
}
public class TcpDemo0 {
    public static void main(String[] args) {

    }
}
8.gif

服务端收到数据后,等待5秒给客户端发送消息。

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

class TcpClient0
{
    public static void main(String[] args) throws Exception
    {
        Socket s = new Socket("192.168.22.38",10004);

        OutputStream out = s.getOutputStream();

        out.write("服务端,你好".getBytes());

        InputStream in = s.getInputStream();

        byte[] buf = new byte[1024];

        int len = in.read(buf);

        System.out.println(new String(buf,0,len));

        s.close();
    }
}
class TcpServer0
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10004);

        Socket s = ss.accept();

        String ip = s.getInetAddress().getHostAddress();

        System.out.println(ip+".....connected");

        InputStream in = s.getInputStream();

        byte[] buf = new byte[1024];

        int len = in.read(buf);

        System.out.println(new String(buf,0,len));

        OutputStream out = s.getOutputStream();

        Thread.sleep(5000);

        out.write("哥们收到,你也好".getBytes());

        s.close();

        ss.close();
    }
}
public class TcpDemo0 {
    public static void main(String[] args) {

    }
}
9.gif

需求:建立一个文本转换服务器。客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端。而且客户端可以不断的进行文本转换。当客户端输入over时,转换结束。

分析:

客户端:
既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考。
源:键盘录入。
目的:网络设备,网络输出流。
而且操作的是文本数据。可以选择字符流。

步骤:

  • 1.建立服务。
  • 2.获取键盘录入。
  • 3.将数据发给服务端。
  • 4.获取服务端返回的大写数据。
  • 5.结束,关资源。

都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲。

服务端:
源:socket读取流。
目的:socket输出流。
都是文本,装饰。

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class TransClient
{
    public static void main(String[] args) throws Exception
    {
        Socket s = new Socket("192.168.23.27",10005);

        //定义读取键盘数据的流对象
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

        //定义目的,将数据写入到socket输出流,发给服务端。
        BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        //定义一个socket读取流,读取服务端返回的大写信息。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;

        while ((line = bufr.readLine())!=null)
        {
            if ("over".equals(line))
                break;
            bufOut.write(line);
            String str = bufIn.readLine();
            System.out.println("server:"+str);
        }

        bufr.close();

        s.close();
    }
}
class TransServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10005);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+"......connected");
        //读取Socket读取流中的数据。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。
        BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line = null;
        while ((line = bufIn.readLine())!=null)
        {
            System.out.println(line);
            bufOut.write(line.toUpperCase());
        }
        s.close();
        ss.close();
    }
}
public class TcpDemo1 {
    public static void main(String[] args) {

    }
}
10.gif

增加刷新缓冲区flush,还是没有数据。

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class TransClient
{
    public static void main(String[] args) throws Exception
    {
        Socket s = new Socket("192.168.23.27",10005);

        //定义读取键盘数据的流对象
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

        //定义目的,将数据写入到socket输出流,发给服务端。
        BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        //定义一个socket读取流,读取服务端返回的大写信息。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;

        while ((line = bufr.readLine())!=null)
        {
            if ("over".equals(line))
                break;
            bufOut.write(line);
            bufOut.flush();
            String str = bufIn.readLine();
            System.out.println("server:"+str);
        }

        bufr.close();

        s.close();
    }
}
class TransServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10005);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+"......connected");
        //读取Socket读取流中的数据。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。
        BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line = null;
        while ((line = bufIn.readLine())!=null)
        {
            System.out.println(line);
            bufOut.write(line.toUpperCase());
        }
        s.close();
        ss.close();
    }
}
public class TcpDemo1 {
    public static void main(String[] args) {

    }
}
11.gif

此例子出现的问题。现象:客户端和服务端都在莫名的等待。为什么呢?因为客户端和服务端都有阻塞式方法。这些方法没有读到结束标记。那么就一直等待而导致两端都在等待。增加结束标记后解决:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class TransClient
{
    public static void main(String[] args) throws Exception
    {
        Socket s = new Socket("192.168.23.27",10005);

        //定义读取键盘数据的流对象
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

        //定义目的,将数据写入到socket输出流,发给服务端。
        BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

        //定义一个socket读取流,读取服务端返回的大写信息。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;

        while ((line = bufr.readLine())!=null)
        {
            if ("over".equals(line))
                break;
            bufOut.write(line);
            bufOut.newLine();
            bufOut.flush();
            String str = bufIn.readLine();
            System.out.println("server:"+str);
        }

        bufr.close();

        s.close();
    }
}
class TransServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10005);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+"......connected");
        //读取Socket读取流中的数据。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。
        BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line = null;
        while ((line = bufIn.readLine())!=null)
        {
            System.out.println(line);
            bufOut.write(line.toUpperCase());
            bufOut.newLine();
            bufOut.flush();
        }
        s.close();
        ss.close();
    }
}
public class TcpDemo1 {
    public static void main(String[] args) {

    }
}
12.gif

用PrintWriter简化写法

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class TransClient
{
    public static void main(String[] args) throws Exception
    {
        Socket s = new Socket("192.168.23.27",10005);

        //定义读取键盘数据的流对象
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

        //定义目的,将数据写入到socket输出流,发给服务端。
//        BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);
        //定义一个socket读取流,读取服务端返回的大写信息。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;

        while ((line = bufr.readLine())!=null)
        {
            if ("over".equals(line))
                break;
            out.println(line);
//            bufOut.write(line);
//            bufOut.newLine();
//            bufOut.flush();
            String str = bufIn.readLine();
            System.out.println("server:"+str);
        }

        bufr.close();

        s.close();
    }
}
class TransServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10005);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+"......connected");
        //读取Socket读取流中的数据。
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。
//        BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);
        String line = null;
        while ((line = bufIn.readLine())!=null)
        {
            System.out.println(line);
            out.println(line.toUpperCase());
//            bufOut.write(line.toUpperCase());
//            bufOut.newLine();
//            bufOut.flush();
        }
        s.close();
        ss.close();
    }
}
public class TcpDemo1 {
    public static void main(String[] args) {

    }
}
13.gif

复制文件

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class TextClient
{
    public static void main(String[] args) throws Exception
    {
        Socket s = new Socket("192.168.23.27",10006);

        BufferedReader bufr = new BufferedReader(new FileReader("IPDemo.java"));

        PrintWriter out = new PrintWriter(s.getOutputStream(),true);

        String line = null;

        while ((line = bufr.readLine())!=null)
        {
            out.println(line);
        }

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String str = bufIn.readLine();

        System.out.println(str);

        bufr.close();

        s.close();
    }
}

class TextServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10006);

        Socket s = ss.accept();

        String ip = s.getInetAddress().getHostAddress();

        System.out.println(ip+"......connected");

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        PrintWriter out = new PrintWriter(new FileWriter("server.txt"),true);

        String line = null;

        while ((line=bufIn.readLine())!=null)
        {
           out.println(line);
        }

        PrintWriter pw = new PrintWriter(s.getOutputStream(),true);

        pw.println("上传成功");

        out.close();

        s.close();

        ss.close();
    }
}
public class TcpDemo2 {
}
14.gif

Snip20191005_6.png

发现文件复制成功,但是程序无法结束。解决办法有两种:

  • 1.添加自定义结束标识符。如over,时间戳。

over作为结束标记

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class TextClient {
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("192.168.23.27", 10006);

        BufferedReader bufr = new BufferedReader(new FileReader("IPDemo.java"));

        PrintWriter out = new PrintWriter(s.getOutputStream(), true);

        String line = null;

        while ((line = bufr.readLine()) != null) {
            out.println(line);
        }

        out.println("over");

//        s.shutdownOutput();//关闭客户端的输出流。相当于给六种加入一个结束标记-1。

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String str = bufIn.readLine();

        System.out.println(str);

        bufr.close();

        s.close();
    }
}

class TextServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10006);

        Socket s = ss.accept();

        String ip = s.getInetAddress().getHostAddress();

        System.out.println(ip + "......connected");

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        PrintWriter out = new PrintWriter(new FileWriter("server.txt"), true);

        String line = null;

        while ((line = bufIn.readLine()) != null) {
            if ("over".equals(line))
                break;
                out.println(line);
        }

        PrintWriter pw = new PrintWriter(s.getOutputStream(), true);

        pw.println("上传成功");

        out.close();

        s.close();

        ss.close();
    }
}

public class TcpDemo2 {
}
17.gif

时间戳作为结束标记--------------有疑问,为什么不能两次都读取DataInputStream里面时间戳作为结束标记。

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class TextClient {
    public static void main(String[] args) throws Exception {
        Socket s = new Socket("192.168.23.27", 10006);

        BufferedReader bufr = new BufferedReader(new FileReader("IPDemo.java"));

        PrintWriter out = new PrintWriter(s.getOutputStream(), true);

        DataOutputStream dos = new DataOutputStream(s.getOutputStream());
        long time = System.currentTimeMillis();
        System.out.println("客户端得到的时间戳");
        System.out.println(time);
        dos.writeLong(time);

        String line = null;

        while ((line = bufr.readLine()) != null) {
            System.out.println("客户端循环里面写入"+line);
            out.println(line);
        }
//        dos.writeLong(time);
        out.println(time+"");
//        out.println("over");

//        s.shutdownOutput();//关闭客户端的输出流。相当于给六种加入一个结束标记-1。

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String str = bufIn.readLine();

        System.out.println(str);

        bufr.close();

        s.close();
    }
}

class TextServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10006);

        Socket s = ss.accept();

        String ip = s.getInetAddress().getHostAddress();

        System.out.println(ip + "......connected");

        DataInputStream dis = new DataInputStream(s.getInputStream());
        long l = dis.readLong();
        System.out.println("服务端得到的时间戳");
        System.out.println(l);

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        PrintWriter out = new PrintWriter(new FileWriter("server.txt"), true);

        String line = null;

        while ((line = bufIn.readLine()) != null) {
//            if ("over".equals(line))
//                break;
            System.out.println("服务端循环里面读取"+line);
            if (String.valueOf(l).equals(line))
                break;
            out.println(line);
        }

        PrintWriter pw = new PrintWriter(s.getOutputStream(), true);

        pw.println("上传成功");

        out.close();

        s.close();

        ss.close();
    }
}

public class TcpDemo2 {
}
18.gif
  • 2.使用系统结束标记,s.shutdownOutput();关闭客户端的输出流。相当于给流中加入一个结束标记-1。
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class TextClient
{
    public static void main(String[] args) throws Exception
    {
        Socket s = new Socket("192.168.23.27",10006);

        BufferedReader bufr = new BufferedReader(new FileReader("IPDemo.java"));

        PrintWriter out = new PrintWriter(s.getOutputStream(),true);

        String line = null;

        while ((line = bufr.readLine())!=null)
        {
            out.println(line);
        }

        s.shutdownOutput();//关闭客户端的输出流。相当于给六种加入一个结束标记-1。
        
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String str = bufIn.readLine();

        System.out.println(str);

        bufr.close();

        s.close();
    }
}

class TextServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10006);

        Socket s = ss.accept();

        String ip = s.getInetAddress().getHostAddress();

        System.out.println(ip+"......connected");

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        PrintWriter out = new PrintWriter(new FileWriter("server.txt"),true);

        String line = null;

        while ((line=bufIn.readLine())!=null)
        {
           out.println(line);
        }

        PrintWriter pw = new PrintWriter(s.getOutputStream(),true);

        pw.println("上传成功");

        out.close();

        s.close();

        ss.close();
    }
}
public class TcpDemo2 {
}
16.gif

你可能感兴趣的:(Java TCP传输)