1 00:00:01,450 --> 00:00:06,480 In our first example, the one we called "simple TCP program", 2 00:00:06,610 --> 00:00:10,960 we could only run one client at a time. 3 00:00:10,960 --> 00:00:17,750 In this example, our goal is going to be to enable several clients to talk to the server, 4 00:00:17,770 --> 00:00:26,710 In parallel. We'll achieve that by using threads, and I'll try to explain the concept of multi threading 5 00:00:26,950 --> 00:00:36,240 real quick right now. A thread in our example is just going to be an instance of the same application. 6 00:00:36,280 --> 00:00:45,640 It's the same code, same operations, same methods - we just run them separately for each new client. On the 7 00:00:45,640 --> 00:00:46,740 server side, 8 00:00:46,750 --> 00:00:53,300 we're going to have one main class, where we're going to have our main method. 9 00:00:53,320 --> 00:01:00,030 The first thing we're going to do in this class is - we're going to open the server socket. 10 00:01:00,100 --> 00:01:09,310 Then we're going to run an infinite loop, where for each incoming connection, we're going to open a new 11 00:01:09,430 --> 00:01:10,150 thread. 12 00:01:10,180 --> 00:01:13,650 Now I repeat - this is a very shortened version. 13 00:01:13,660 --> 00:01:18,090 We're going to go through the entire code later. For now, 14 00:01:18,100 --> 00:01:24,730 this is what threads look like for every new client that connects to the server - 15 00:01:24,730 --> 00:01:26,820 we run a new thread, 16 00:01:26,950 --> 00:01:37,090 this calls a run method in a server thread that we create for every new connection. 17 00:01:37,090 --> 00:01:44,700 So to sum up, whenever a new connection comes to the server, we create a regular socket, 18 00:01:44,770 --> 00:01:52,450 by accepting that connection - that's coming through the server socket, and then we create a thread for 19 00:01:52,450 --> 00:01:55,360 that particular connection. 20 00:01:55,390 --> 00:02:01,640 After that, we just go back to the loop and wait for the new connection to show up. 21 00:02:01,810 --> 00:02:02,380 All right. 22 00:02:02,380 --> 00:02:06,400 Hopefully this will clear up as we go through the code. 23 00:02:06,550 --> 00:02:09,500 I'm going to open Eclipse. 24 00:02:09,640 --> 00:02:21,980 I'm going to create a new package and I'm going to name it simple_tcp_multithread. This time we'll need 25 00:02:22,040 --> 00:02:28,630 two server classes. One is ServerMain, 26 00:02:31,310 --> 00:02:35,990 and the other one is ServerThread. 27 00:02:39,630 --> 00:02:47,970 We'll copy the Client class from our previous example, because the code in the client is not really going 28 00:02:47,970 --> 00:02:48,560 to change. 29 00:02:48,570 --> 00:02:50,680 We're only changing the server. 30 00:02:50,700 --> 00:02:56,310 We're only enabling the server to accept several connections at a time. 31 00:02:56,400 --> 00:03:03,790 So I'm just going to copy the client into our new package. 32 00:03:03,810 --> 00:03:06,150 All right, let's get going. 33 00:03:06,150 --> 00:03:09,620 I'm going to start from the ServerMain class. 34 00:03:09,720 --> 00:03:14,000 The first thing we're going to need is going to be the main method. 35 00:03:15,810 --> 00:03:20,990 And then inside our main method, we're going to have the try-catch block 36 00:03:21,030 --> 00:03:24,530 again - we're familiar with that. 37 00:03:24,730 --> 00:03:33,070 We're going to do the printStackTrace() in the catch block, and in the try block we're going to call 38 00:03:33,130 --> 00:03:41,470 new ServerMain(). Then, we're going to create this ServerMain method. 39 00:03:41,540 --> 00:03:43,210 It's going to be public, 40 00:03:51,750 --> 00:03:56,850 and the first thing we're going to need here is the server socket. 41 00:04:06,930 --> 00:04:10,750 We'll use 2020 for our port number again. 42 00:04:10,920 --> 00:04:12,270 And I'm going to press 43 00:04:12,270 --> 00:04:17,280 Ctrl + Shift +O to import all and necessary packets. 44 00:04:17,280 --> 00:04:23,340 Let's print out a message just so we know where we are when the program runs. 45 00:04:23,340 --> 00:04:32,340 We're gonna say "Port 2020 is now open." 46 00:04:32,350 --> 00:04:35,680 Now we need that infinite while loop, 47 00:04:35,680 --> 00:04:37,570 I'm going to add a comment here - 48 00:04:47,820 --> 00:04:53,850 you create an infinite loop by just typing "true" in the condition. 49 00:04:53,870 --> 00:05:03,390 So whatever happens inside the loop, we're always going to come back and do another run through the loop. 50 00:05:03,420 --> 00:05:12,360 So the point of this loop is to create a new thread for every new client that shows up. The first step 51 00:05:12,360 --> 00:05:15,930 would be to create a socket for every new client. 52 00:05:15,930 --> 00:05:24,420 So we're going to create the socket object, and we get the socket object when we accept a connection 53 00:05:24,450 --> 00:05:34,470 coming into the server socket. Again, I'm going to press Ctrl + Shift + O to import the socket package, 54 00:05:34,560 --> 00:05:37,530 and now I'm going to work on the thread. 55 00:05:37,530 --> 00:05:45,120 So now you're going to have to bear with me, I'm going to explain the code as I go, and some of it will 56 00:05:45,180 --> 00:05:48,240 only become clear later. 57 00:05:48,240 --> 00:05:51,740 So let's just type it in and see what happens. 58 00:05:51,750 --> 00:05:58,950 First I'm going to create a ServerThread object, and I'm going to have to use a constructor from the 59 00:05:58,950 --> 00:06:00,630 ServerThread class. 60 00:06:00,630 --> 00:06:07,290 Now since we don't have anything in that class yet, we're going to have this warning throughout typing 61 00:06:07,290 --> 00:06:16,800 this code, but don't worry about that - we're gonna resolve that later. 62 00:06:17,260 --> 00:06:27,730 So here's our object. We're going to say new ServerThread and we're going to forward the socket as the 63 00:06:27,730 --> 00:06:28,810 argument. 64 00:06:29,380 --> 00:06:32,500 Here's that error that I was talking about. 65 00:06:32,800 --> 00:06:38,070 We're just gonna ignore that for now and it's actually going to resolve itself. 66 00:06:38,080 --> 00:06:52,370 Now, we're going to need a Thread - Java already has a Thread class, since threads are a pretty common conception. 67 00:06:52,570 --> 00:07:03,340 We're going to forward our server_thread object as an argument, and then we're going to say thread.start(). 68 00:07:03,390 --> 00:07:13,890 Now what this means is - whenever we run into this line, we're going to call a run() method in the ServerThread 69 00:07:13,890 --> 00:07:22,260 ServerThread class - you'll realize later on what that means since right now we haven't built our run() method 70 00:07:22,260 --> 00:07:22,800 yet. 71 00:07:23,010 --> 00:07:31,530 So let's go to our ServerThread class, and get into it right now. Our ServerThread class is going 72 00:07:31,530 --> 00:07:33,990 to have to "implement Runnable". 73 00:07:38,680 --> 00:07:39,490 By the way, 74 00:07:39,520 --> 00:07:48,490 this could be done in a different manner, but we're going to use Runnable. What Runnable is - it's pretty 75 00:07:48,490 --> 00:07:59,830 much an interface and is like a template for an object that is intended to be executed by a thread. 76 00:07:59,830 --> 00:08:09,970 It defines a single method which is >>run()<< - we haven't defined it yet, but we are going to - and that run() method 77 00:08:10,060 --> 00:08:16,120 is meant to contain the code that is executed by the thread. 78 00:08:16,120 --> 00:08:23,530 This is going to make much more sense when we run the code so let's get into it and hopefully it will 79 00:08:23,530 --> 00:08:27,730 clear up. Now, before we add that run() method, 80 00:08:27,730 --> 00:08:32,320 we need to create the constructor that I mentioned in our previous class. 81 00:08:32,320 --> 00:08:40,420 If you're not familiar with constructors - a constructor is kind of a special method, that is called when 82 00:08:40,630 --> 00:08:42,510 an object is initiated. 83 00:08:42,640 --> 00:08:50,450 So a class constructor initializes instances - or objects - of that class. 84 00:08:50,590 --> 00:08:57,910 In our case, we need to initialize the object that we forwarded from our ServerMain class, and that 85 00:08:57,910 --> 00:09:00,760 would be our socket object. 86 00:09:00,850 --> 00:09:09,970 We're going to define that object as private, because we don't want other threads to be able - other threads 87 00:09:10,030 --> 00:09:16,260 or classes - to be able to access a socket in a particular thread. 88 00:09:16,390 --> 00:09:26,700 So it's going to be private Socket socket, and then we're going to say public server_thread. 89 00:09:26,800 --> 00:09:35,590 Now this method has to be public because we need to access it - or we need to call it from another class, 90 00:09:35,620 --> 00:09:38,650 and that class is the ServerMain class. 91 00:09:41,500 --> 00:09:50,740 And here we are defining the object that is being forwarded, and then we're going to say this.socket 92 00:09:50,890 --> 00:09:52,950 this.socket = socket. 93 00:09:53,170 --> 00:09:59,980 We're using the >>this<< keyword, because our objects are named the same. 94 00:09:59,980 --> 00:10:06,400 But if you're wondering which socket is which, you just need to click - or at least, if you're using Eclipse - 95 00:10:06,670 --> 00:10:14,130 you just need to click on one of the objects and it's going to tell you which one of them is being referred 96 00:10:14,180 --> 00:10:14,860 here. 97 00:10:14,860 --> 00:10:17,910 So this is the socket we're talking about. 98 00:10:18,040 --> 00:10:27,670 This socket - this object - is going to become this newly defined object in our constructor. 99 00:10:27,730 --> 00:10:35,830 I'm going to press Ctrl + Shift + O to import the Socket package, and then we can move on to our run() 100 00:10:35,980 --> 00:10:37,390 method. 101 00:10:37,390 --> 00:10:46,770 I'm going to have to use @Override here because Java's Thread class already has its own run() method. 102 00:10:46,780 --> 00:10:53,830 So in order for us to be able to use our own run() method ,we're just going to use this @Override thing. 103 00:10:54,220 --> 00:11:03,520 run() is going to be - public void run() - and then we're going to have the try-catch block inside of it. 104 00:11:03,790 --> 00:11:13,960 Our catch block is going to have the regular printStackTrace(), and our try block is actually going to 105 00:11:13,960 --> 00:11:21,760 have all of the code that defines the protocol for the communication between the server and our client. 106 00:11:22,130 --> 00:11:27,870 I'm actually going to be a bit lazy and copy that from our previous example. 107 00:11:30,430 --> 00:11:32,730 I'm going to copy. 108 00:11:32,800 --> 00:11:50,310 No I'm actually going to go to the first one and I'm going to copy all of this. 109 00:11:50,370 --> 00:11:53,600 I'm going to edit this a bit. 110 00:11:53,670 --> 00:11:58,560 I'm going to add a printout here, that a new client has connected. 111 00:12:02,350 --> 00:12:06,010 And then the server is going to say to the client: 112 00:12:06,160 --> 00:12:06,970 "Welcome! What's your name?" 113 00:12:06,970 --> 00:12:08,700 "Welcome! What's your name?" 114 00:12:10,970 --> 00:12:18,280 I'm going to save that, and I'm going to go back to ServerMain to check things here. 115 00:12:18,290 --> 00:12:19,330 Everything seems OK. 116 00:12:19,340 --> 00:12:23,780 I'm going to save that too and then I'm going to open the client. 117 00:12:23,840 --> 00:12:28,400 The client is not going to be guessing any numbers this time. 118 00:12:28,550 --> 00:12:32,620 So we're going to delete all of this instead. 119 00:12:32,630 --> 00:12:37,220 We're going to just accept the message from the server, 120 00:12:45,300 --> 00:12:47,560 print it out in our console. 121 00:12:47,560 --> 00:12:48,490 We're going to say - 122 00:12:56,170 --> 00:13:05,080 and then we're going to store whatever the user types in into the same string. 123 00:13:12,040 --> 00:13:22,430 And then we're going to send that out to the server. 124 00:13:22,670 --> 00:13:23,360 That's it. 125 00:13:23,370 --> 00:13:24,320 That should work. 126 00:13:24,320 --> 00:13:34,740 I'm going to save this and then run it. We're going to run ServerMain. So we're again running only the 127 00:13:34,740 --> 00:13:37,110 classes that have the main method. 128 00:13:42,120 --> 00:13:45,090 And then let's run our first client. 129 00:13:47,890 --> 00:13:51,190 I'm going to switch to the client's console. 130 00:13:51,450 --> 00:13:53,350 It's asking me what's my name. 131 00:13:53,370 --> 00:14:01,930 I'm going to say "Luke" for example, and then I'm going to run another client. 132 00:14:05,070 --> 00:14:13,080 This time, I'm not going to answer to server's question, and I'm going to run another client. 133 00:14:15,660 --> 00:14:20,430 So at this point we have two clients running. 134 00:14:20,430 --> 00:14:23,400 Let's check that out in the console. 135 00:14:23,400 --> 00:14:31,410 So we have client three here OK. 136 00:14:31,420 --> 00:14:35,960 So this is the second client and this is the third client. 137 00:14:38,130 --> 00:14:46,590 I'm going to type another name into the second client and now my second client has disconnected. 138 00:14:46,800 --> 00:14:53,160 And then I'm going to type in something else into the third client. 139 00:14:53,460 --> 00:14:56,900 Let's say "Laura" for example. 140 00:14:56,940 --> 00:14:57,770 All right. 141 00:14:57,820 --> 00:15:05,080 Now all of my three clients have disconnected but the server is actually still running. 142 00:15:05,110 --> 00:15:09,330 If we go to "Clients" - it says "terminated" here. 143 00:15:09,400 --> 00:15:18,570 So I'm going to close this console, and then I'm going to close the third client's console, and I'm only 144 00:15:18,570 --> 00:15:25,590 left with my server's console. And I can see here that it's still running, because I have this "terminate" 145 00:15:25,590 --> 00:15:28,140 button still available. 146 00:15:28,140 --> 00:15:31,810 I'm going to click here and now we're done. 147 00:15:31,830 --> 00:15:35,430 Now I can close the console for the server too.