JAVA之旅(三十三)——TCP传输,互相(伤害)传输,复制文件,上传图片,多并发上传,多并发登录

释放双眼,带上耳机,听听看~!

JAVA之旅(三十三)——TCP传输,互相(伤害)传输,复制文件,上传图片,多并发上传,多并发登录


我们继续网络编程

一.TCP

说完UDP,我们就来说下我们应该重点掌握的TCP了

  • TCP传输

  • Socket和ServiceSocket

    • 建立客户端和服务端
    • 建立连接后,通过Socket中的IO流进行数据的传输
    • 关闭Socket

同样的,我们的客户端和服务端都是两个独立的应用

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

所以我们用代码来看下他的步骤

客户端


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1package com.lgl.hellojava;
2
3import java.io.IOException;
4import java.io.InputStream;
5import java.io.OutputStream;
6import java.net.ServerSocket;
7import java.net.Socket;
8import java.net.UnknownHostException;
9
10public class TcpClient {
11
12    public static void main(String[] args) {
13        try {
14            //1.创建客户端的服务,传地址和端口
15            Socket s = new Socket("192.168.1.102",10000);
16            //2.为了发送数据,应该获得socket流中的输出流
17            OutputStream out = s.getOutputStream();
18            out.write("你好".getBytes());
19            s.close();
20        } catch (UnknownHostException e) {
21            // TODO Auto-generated catch block
22            e.printStackTrace();
23        } catch (IOException e) {
24            // TODO Auto-generated catch block
25            e.printStackTrace();
26        }
27    }
28}
29
30
31

服务端


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
1package com.lgl.hellojava;
2
3import java.io.IOException;
4import java.io.InputStream;
5import java.net.ServerSocket;
6import java.net.Socket;
7
8/**
9 * 定义端点接收数据打印出来
10 * 服务端:
11 * 1.建立服务端的socket服务,servicesocket,并监听一个端口
12 * 2.获取连接过来的客户端对象,通过accept方法,这个方法是阻塞的,没有连接就会等
13 * 3.客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该对象的读取流
14 * 4.关闭服务端(可选操作)
15 * @author LGL
16 *
17 */
18public class TcpService {
19    public static void main(String[] args) {
20        try {
21            //1.建立连接,监听端口
22            ServerSocket ss = new ServerSocket(10000);
23            //2.连接客户端对象
24            Socket accept = ss.accept();
25            //获取ip
26            String ip = accept.getInetAddress().getHostAddress();
27            //3.获取客户端发送过来的数据
28            InputStream in = accept.getInputStream();
29            //4.开始读取
30            byte [] buf = new byte[1024];
31            int len = in.read(buf);
32            System.out.println(new String(buf,0,len));
33            //5.关闭
34            ss.close();
35        } catch (IOException e) {
36            // TODO Auto-generated catch block
37            e.printStackTrace();
38        }
39    }
40}
41
42

二.TCP互相传输

我们在来写一个实例去说明,他们的互访动作,这里为了写起来方便,就写在一个类中了


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
1package com.lgl.hellojava;
2
3import java.io.IOException;
4import java.io.InputStream;
5import java.io.OutputStream;
6import java.net.ServerSocket;
7import java.net.Socket;
8import java.net.UnknownHostException;
9
10/**
11 * 客户端发送信息,服务端收到,反馈信息
12 *
13 * @author LGL
14 *
15 */
16public class Tcp {
17
18    public static void main(String[] args) {
19        try {
20            Socket s = new Socket("192.168.1.102", 10005);
21            OutputStream out = s.getOutputStream();
22            out.write("我是客户端".getBytes());
23            InputStream in = s.getInputStream();
24            byte[] buf = new byte[1024];
25            int len = in.read(buf);
26            System.out.println(new String(buf, 0, len));
27            s.close();
28        } catch (UnknownHostException e) {
29            // TODO Auto-generated catch block
30            e.printStackTrace();
31        } catch (IOException e) {
32            // TODO Auto-generated catch block
33            e.printStackTrace();
34        }
35    }
36}
37/**
38 * 服务端
39 * @author LGL
40 *
41 */
42class Server {
43    public static void main(String[] args) {
44        try {
45            ServerSocket ss = new ServerSocket(10005);
46            Socket s = ss.accept();
47            InputStream in = s.getInputStream();
48            byte[] buf = new byte[1024];
49            int len = in.read(buf);
50            System.out.println(new String(buf, 0, len));
51
52            OutputStream out = s.getOutputStream();
53            out.write("收到后反馈".getBytes());
54            s.close();
55            ss.close();
56        } catch (IOException e) {
57            // TODO Auto-generated catch block
58            e.printStackTrace();
59        }
60    }
61}
62
63

三.复制文件

同样的这里也是使用的流,我们具体来看下怎么去操作,我们同样的,写在一个类中


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
1package com.lgl.socket;
2
3import java.io.BufferedReader;
4import java.io.FileReader;
5import java.io.FileWriter;
6import java.io.IOException;
7import java.io.InputStreamReader;
8import java.io.PrintWriter;
9import java.net.ServerSocket;
10import java.net.Socket;
11import java.net.UnknownHostException;
12
13public class FileClient {
14
15    public static void main(String[] args) {
16        try {
17            Socket s = new Socket("192.168.1.102", 10006);
18            BufferedReader bufr = new BufferedReader(new FileReader("test.txt"));
19            PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
20            String line = null;
21            while ((line = bufr.readLine()) != null) {
22                pw.println(line);
23            }
24            pw.print("over");
25            BufferedReader bufIn = new BufferedReader(new InputStreamReader(
26                    s.getInputStream()));
27            String str = bufIn.readLine();
28            System.out.println(str);
29
30            bufr.close();
31            s.close();
32        } catch (UnknownHostException e) {
33            // TODO Auto-generated catch block
34            e.printStackTrace();
35        } catch (IOException e) {
36            // TODO Auto-generated catch block
37            e.printStackTrace();
38        }
39    }
40}
41
42class FileServer {
43    public static void main(String[] args) {
44        try {
45            ServerSocket ss = new ServerSocket(10006);
46            Socket s = ss.accept();
47
48            BufferedReader bufIn = new BufferedReader(new InputStreamReader(
49                    s.getInputStream()));
50            PrintWriter out = new PrintWriter(new FileWriter("test1.txt"), true);
51            String line = null;
52            while ((line = bufIn.readLine()) != null) {
53                if ("over".equals(line))
54                    break;
55                out.println(line);
56            }
57            PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
58            pw.println("上传成功");
59
60            out.close();
61            s.close();
62            ss.close();
63
64        } catch (IOException e) {
65            // TODO Auto-generated catch block
66            e.printStackTrace();
67        }
68    }
69}
70
71

四.上传图片

我们再来看下图片是怎么上传的,我们先来分析下步骤

客户端

  • 1.服务端点

  • 2.读取客户端已有的图片数据

  • 3.通过socket,发送给服务端

  • 4.读取服务端反馈的信息

  • 5.关闭资源


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
1**
2 * 客户端
3 *
4 * @author LGL
5 *
6 */
7public class PicClient {
8
9    public static void main(String[] args) {
10        try {
11            Socket s = new Socket("192.168.1.102", 10009);
12            FileInputStream fis = new FileInputStream("1.png");
13            OutputStream out = s.getOutputStream();
14            byte[] buf = new byte[1024];
15            int len = 0;
16            while ((len = fis.read(buf)) != -1) {
17                out.write(buf, 0, len);
18            }
19            //告訴服务端数据写完
20            s.shutdownInput();
21            InputStream in = s.getInputStream();
22            byte[] bufn = new byte[1024];
23            int num = in.read(bufn);
24            System.out.println(new String(bufn, 0, num));
25            fis.close();
26            s.close();
27        } catch (UnknownHostException e) {
28            // TODO Auto-generated catch block
29            e.printStackTrace();
30        } catch (IOException e) {
31            // TODO Auto-generated catch block
32            e.printStackTrace();
33        }
34    }
35}
36
37

服务端

直接看代码


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2/**
3 * 服務端
4 * @author LGL
5 *
6 */
7class PicServer {
8    public static void main(String[] args) {
9        try {
10            ServerSocket ss = new ServerSocket(10009);
11            Socket s = ss.accept();
12            InputStream in = s.getInputStream();
13            FileOutputStream fos = new FileOutputStream("2.png");
14            byte[] buf = new byte[1024];
15            int len = 0;
16            while ((len = in.read(buf)) != -1) {
17                fos.write(buf, 0, len);
18            }
19
20            OutputStream out = s.getOutputStream();
21            out.write("上传成功".getBytes());
22            fos.close();
23            s.close();
24            ss.close();
25        } catch (IOException e) {
26            // TODO Auto-generated catch block
27            e.printStackTrace();
28        }
29    }
30}
31

其实跟I/O区别真不大,但是概念一定要了解清楚

五.多并发上传

多并发这个概念就是多人互动了,这对服务器的负荷还是有考究的,这里呢,我们就模拟一下,多人上传图片的场景,我们是怎么做的?我们还是在上传图片的那份代码上更改

首先我们可以确定的是,这是服务端的代码

  • 这个服务端有个局限性,当A客户端连接之后,被服务端获取到,服务端就在执行代码了,这个时候如果B客户端连接只有等待,这就是我们需要多并发的原因了,为了让多个客户端同时连接,服务端最好就是讲每个客户端封装到一个单独的线程中,这样就可以同时处理多个客户端请求

如何定义线程?

  • 只要明确了每个客户端要在服务端执行的代码即可


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
1
2/**
3 * 服務端
4 *
5 * @author LGL
6 *
7 */
8class PicServer {
9    public static void main(String[] args) {
10        try {
11            ServerSocket ss = new ServerSocket(10009);
12            while (true) {
13                Socket s = ss.accept();
14                new Thread(new PicThread(s)).start();
15            }
16        } catch (IOException e) {
17            // TODO Auto-generated catch block
18            e.printStackTrace();
19        }
20    }
21}
22/**
23 * 并发线程
24 * @author LGL
25 *
26 */
27class PicThread implements Runnable {
28
29    private Socket s;
30
31    public PicThread(Socket s) {
32        this.s = s;
33    }
34
35    @Override
36    public void run() {
37        try {
38            String ip = s.getInetAddress().getHostAddress();
39            System.out.println("ip:" + ip);
40
41            long millis = System.currentTimeMillis();
42            File file = new File(millis + ".png");
43            InputStream in = s.getInputStream();
44            FileOutputStream fos = new FileOutputStream(file);
45            byte[] buf = new byte[1024];
46            int len = 0;
47            while ((len = in.read(buf)) != -1) {
48                fos.write(buf, 0, len);
49            }
50
51            OutputStream out = s.getOutputStream();
52            out.write("上传成功".getBytes());
53            fos.close();
54            s.close();
55        } catch (Exception e) {
56
57            throw new RuntimeException("上传失败");
58        }
59
60    }
61
62}
63

其实我写的代码还是有点烂的,但是思想在就好,我们得先把思想学会了

六.多并发登录

上面说的多并发的上传,实在服务端端,现在我们来说下登录,是作用在客户端


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
1package com.lgl.socket;
2
3import java.io.BufferedReader;
4import java.io.FileReader;
5import java.io.IOException;
6import java.io.InputStreamReader;
7import java.io.PrintWriter;
8import java.net.ServerSocket;
9import java.net.Socket;
10import java.net.UnknownHostException;
11
12public class LoginClient {
13
14    public static void main(String[] args) {
15        try {
16            Socket s = new Socket("192.168.1.102", 10008);
17            BufferedReader bufr = new BufferedReader(new InputStreamReader(
18                    System.in));
19            PrintWriter out = new PrintWriter(s.getOutputStream(), true);
20            BufferedReader bufIn = new BufferedReader(new InputStreamReader(
21                    s.getInputStream()));
22            for (int i = 0; i < 3; i++) {
23                String line = bufr.readLine();
24                if (line == null) {
25                    break;
26                }
27                out.println(line);
28
29                String info = bufIn.readLine();
30                System.out.println("info:" + info);
31                if (info.contains("欢迎")) {
32                    break;
33                }
34            }
35            bufr.close();
36            s.close();
37        } catch (UnknownHostException e) {
38            // TODO Auto-generated catch block
39            e.printStackTrace();
40        } catch (IOException e) {
41            // TODO Auto-generated catch block
42            e.printStackTrace();
43        }
44    }
45}
46
47/**
48 * 服务端
49 *
50 * @author LGL
51 *
52 */
53class LoginServer {
54    public static void main(String[] args) {
55        try {
56            ServerSocket ss = new ServerSocket(10008);
57            while (true) {
58                Socket s = ss.accept();
59                new Thread(new UserThread(s)).start();
60            }
61        } catch (IOException e) {
62            // TODO Auto-generated catch block
63            e.printStackTrace();
64        }
65    }
66}
67
68/**
69 * 并发登陆
70 *
71 * @author LGL
72 *
73 */
74class UserThread implements Runnable {
75
76    private Socket s;
77
78    public UserThread(Socket s) {
79        this.s = s;
80    }
81
82    @Override
83    public void run() {
84        for (int i = 0; i < 3; i++) {
85            try {
86                BufferedReader bufrIn = new BufferedReader(
87                        new InputStreamReader(s.getInputStream()));
88                String name = bufrIn.readLine();
89
90                // 模拟读取数据库的用户名
91                BufferedReader bufr = new BufferedReader(new FileReader(
92                        "user.txt"));
93
94                PrintWriter out = new PrintWriter(s.getOutputStream(), true);
95
96                String line = null;
97
98                boolean flag = false;
99                while ((line = bufr.readLine()) != null) {
100                    if (line.equals(name)) {
101                        flag = true;
102                        break;
103                    }
104                }
105                if (flag) {
106                    System.out.println("已登录");
107                    out.print("欢迎");
108                } else {
109                    System.out.println("重新登录");
110                    out.println("用户名不存在");
111                }
112                s.close();
113
114            } catch (IOException e) {
115                // TODO Auto-generated catch block
116                e.printStackTrace();
117            }
118
119        }
120    }
121
122}
123

OK,这些代码中可能会存在一些错误,因为代码并没有去实际的验证中,我写的时候也是跟着思想去走的,这样写代码是极为友好的,这就是TCP的冰山一角了,不过关于这些,还有很多知识点,我们要做的就是把思想给掌握了,万变不理其中

好的,最近写文的时间,有点懈怠了,看来要发力了,嘻嘻,

有兴趣的加群:555974449 一起来玩玩吧!

给TA打赏
共{{data.count}}人
人已打赏
安全技术

详解Node.js API系列 Http模块(1) 构造一个简单的静态页服务器

2021-12-21 16:36:11

安全技术

从零搭建自己的SpringBoot后台框架(二十三)

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索