1 00:00:00,660 --> 00:00:05,430 In this lesson we'll go back to the code that we wrote in the previous lessons, 2 00:00:05,580 --> 00:00:11,680 and I'm going to explain everything again, and give you some more details. 3 00:00:11,700 --> 00:00:14,240 We're going to start from the server. 4 00:00:14,460 --> 00:00:21,940 As I've mentioned before, the entry point to any application is its main method. 5 00:00:22,080 --> 00:00:26,500 When you run a program, that's what it will look for. 6 00:00:26,550 --> 00:00:31,890 It's going to look for the main method to start executing from. Now, 7 00:00:31,980 --> 00:00:39,300 this is a regular main method that you'll be using in pretty much all of your Java applications. 8 00:00:39,300 --> 00:00:46,140 And the only two keywords we need to worry about right now, are "public" and "void". 9 00:00:46,140 --> 00:00:49,680 So "main" is pretty much always going to be - public static void - 10 00:00:49,680 --> 00:00:52,440 and it's going to forward "String[] args". 11 00:00:52,440 --> 00:01:02,100 This is an array of arguments, but "public" and "void" is what we'll need in these lessons. 12 00:01:02,130 --> 00:01:05,410 So let me just shortly explain those. 13 00:01:05,430 --> 00:01:13,740 We will use "public" for a method any time we need a certain method to be accessible from other classes, 14 00:01:13,740 --> 00:01:23,310 and then "void" means that this method doesn't really return any value - it doesn't return 15 00:01:23,340 --> 00:01:24,570 any data. 16 00:01:24,570 --> 00:01:30,460 So, when you call the main method, you don't need it to for example calculate anything for you, or print out 17 00:01:30,480 --> 00:01:36,100 something for you, you just need it as an entry point to your application. 18 00:01:36,120 --> 00:01:40,350 Now to explain this try-catch block a bit better, 19 00:01:40,350 --> 00:01:45,150 I'm going to use an example. In this example we're trying to divide 20 00:01:45,150 --> 00:01:51,460 num2, or rather the value of num2 with the value of num1. 21 00:01:51,660 --> 00:01:54,780 They are both defined as integers right here, 22 00:01:54,780 --> 00:02:00,610 and that's when we get into the try block. And then, this is obviously a comment. 23 00:02:00,720 --> 00:02:11,370 And here would define num1 as zero and num2 as 62 divided by the value of num1, which in 24 00:02:11,370 --> 00:02:13,370 this case is zero. 25 00:02:13,380 --> 00:02:23,100 So if this could be done - if this was OK - if the value of num1 was one, then we would be able to see 26 00:02:23,130 --> 00:02:26,250 this printout: "Try block message". 27 00:02:26,370 --> 00:02:31,400 I could have put something that makes more sense here, but let's just go with it. 28 00:02:31,410 --> 00:02:39,350 So if this was OK - if this line of code was all right, we would be able to see this instead. 29 00:02:39,420 --> 00:02:47,250 Since this is a forbidden operation, we are thrown to the catch block. The catch block could be made to 30 00:02:47,250 --> 00:02:54,480 be much more useful than this. For example, you could prompt the user to insert a different number or 31 00:02:54,480 --> 00:02:55,570 something like that. 32 00:02:55,680 --> 00:03:01,470 But the point of this example is just to show what happens in a try-catch block. 33 00:03:01,470 --> 00:03:09,140 So in this case we have a print line which says "Error: don't divide in number by zero", 34 00:03:09,150 --> 00:03:17,700 so we pretty much know that the only issue that could happen in this situation is if a user gives us 35 00:03:17,820 --> 00:03:18,660 a zero. 36 00:03:18,720 --> 00:03:22,590 So that's what we would get - this printout. 37 00:03:22,650 --> 00:03:30,930 Obviously, we would skip this print out because this is the line that would cause us to go to the catch 38 00:03:30,930 --> 00:03:32,060 block. 39 00:03:32,130 --> 00:03:39,240 So, once we're out of the catch block, we're going to get another printout that says "I'm out of 40 00:03:39,240 --> 00:03:41,550 try-catch block in Java." 41 00:03:41,550 --> 00:03:47,960 So this is what our output in total would look like after going through this code. 42 00:03:47,970 --> 00:03:54,520 Now, we didn't have an explanation like this in our catch block in our program. 43 00:03:54,720 --> 00:03:59,640 So I'm gonna change something for example in the client. 44 00:03:59,640 --> 00:04:05,580 I'm going to try to connect to a wrong port number to see what happens. 45 00:04:05,580 --> 00:04:12,000 So we're going to see this printStackTrace() method in action. 46 00:04:12,000 --> 00:04:21,660 I'm going to save this first and then we'll run the server - and then we see that the server is running - "Port 47 00:04:21,660 --> 00:04:27,880 2020 is open", and now we're going to run the client and the first thing the client is going to do is 48 00:04:27,880 --> 00:04:32,110 it's going to try to connect to the wrong port number. 49 00:04:35,120 --> 00:04:38,000 We can see the printout in our console window. 50 00:04:38,000 --> 00:04:40,690 I'm not going to go through all of these errors - 51 00:04:40,760 --> 00:04:44,970 they're actually all related to the first one that says "Connection refused". 52 00:04:44,970 --> 00:04:52,490 Now obviously, the connection is going to be refused because in our client we tried to target a port 53 00:04:52,730 --> 00:05:01,850 that isn't open on our listening server. We can close these now and the server is still running because 54 00:05:01,880 --> 00:05:04,780 it's never got out of this line. 55 00:05:04,790 --> 00:05:11,750 So it's still in this line, waiting for a legitimate connection to come and to be accepted. 56 00:05:11,750 --> 00:05:19,700 So I'm just going to stop the server and close all of these windows, and then I'm going to change the 57 00:05:19,700 --> 00:05:24,420 port number back to 2020, and I'm going to save that. 58 00:05:24,430 --> 00:05:24,950 All right. 59 00:05:24,950 --> 00:05:32,510 We can move on now with our explanations. As I've mentioned before when we run our program, 60 00:05:32,600 --> 00:05:36,530 the first thing it gets into is the main method. 61 00:05:36,620 --> 00:05:42,480 Then we get into the try block where we can see "new Server()" 62 00:05:42,500 --> 00:05:51,050 This is when we call this method right here - and then the first thing we do in this method is: we create 63 00:05:51,110 --> 00:05:55,460 the server socket. Creating a server socket 64 00:05:55,460 --> 00:06:03,680 pretty much means that we're going to reserve, or - we're going to open a certain port, that we're going 65 00:06:03,680 --> 00:06:06,050 to use for this application. 66 00:06:06,050 --> 00:06:12,890 Then we create a regular socket that we're going to use to communicate to the client. 67 00:06:12,950 --> 00:06:21,830 We get this socket, or rather - this socket can be used as soon as we have an incoming connection that 68 00:06:21,830 --> 00:06:23,030 we can accept. 69 00:06:23,030 --> 00:06:31,400 So as I've mentioned earlier this line right here is blocking the rest of the program until an incoming 70 00:06:31,400 --> 00:06:33,740 connection shows up. 71 00:06:33,740 --> 00:06:39,700 This next line is I hope pretty intuitive, since this is just a printout. 72 00:06:39,710 --> 00:06:45,870 It says a client has connected, and then we're pulling an IP address from the socket. 73 00:06:45,920 --> 00:06:54,050 As I've said before, we use this socket method to create a socket object, and this socket object holds 74 00:06:54,140 --> 00:07:00,260 all the important information that's relevant to our connection, which means we can pull the IP address 75 00:07:00,350 --> 00:07:03,050 of the client from this object. 76 00:07:03,170 --> 00:07:10,430 And that's exactly what we're doing in this line - or in this little part right here. 77 00:07:10,460 --> 00:07:11,220 All right. 78 00:07:11,220 --> 00:07:12,560 Onto the buffers. 79 00:07:12,560 --> 00:07:15,910 Now obviously we have two streams of data. 80 00:07:15,920 --> 00:07:20,240 We have the incoming stream of data and the outgoing stream of data. 81 00:07:20,330 --> 00:07:24,730 We're going to use the in_socket for the incoming stream of data - 82 00:07:24,740 --> 00:07:32,300 that is the data that is coming from the client to the server, and then the out_socket is going to be 83 00:07:32,300 --> 00:07:40,080 used for the outgoing data which are all the messages that the server sends to the client. 84 00:07:40,100 --> 00:07:45,680 You may be wondering why do we need three methods here for the socket. 85 00:07:45,680 --> 00:07:53,540 Those methods would be BufferedReader, InputStreamReader, and getInputStream. For the getInputStream, 86 00:07:53,540 --> 00:07:56,640 obviously we're looking at the same socket 87 00:07:56,660 --> 00:08:05,030 in both cases. For incoming data and for the outgoing data, a socket is like a door - you can come in 88 00:08:05,090 --> 00:08:06,670 and you can get out. 89 00:08:06,680 --> 00:08:13,920 So by using getInputStream, we're selecting the data that we want to look at. 90 00:08:13,940 --> 00:08:22,040 Now, this data is going to come in pretty much like gibberish. If you've ever used Wireshark, 91 00:08:22,040 --> 00:08:26,020 you know what I'm talking about - it's going to be messed up. 92 00:08:26,060 --> 00:08:34,370 That's why we need the InputStreamReader to switch that unreadable data into something a user - or a 93 00:08:34,370 --> 00:08:35,360 human being 94 00:08:35,360 --> 00:08:37,100 in this case - can understand. 95 00:08:37,120 --> 00:08:45,410 So that's going to switch that to gibberish into readable text. And then, the BufferedReader - 96 00:08:45,410 --> 00:08:51,890 we need that to put all of that data into a buffer. 97 00:08:51,890 --> 00:08:55,960 I'm going to use an additional example to explain buffers, 98 00:08:56,090 --> 00:09:06,200 and also this example should explain this "true" argument that we used in our PrintWriter methods 99 00:09:06,230 --> 00:09:09,350 for the outgoing socket. 100 00:09:09,350 --> 00:09:15,010 So this is the example, and this is the website if you want to go and check it out. 101 00:09:15,200 --> 00:09:22,550 It simulates an application - or two applications - that are talking to each other. On the left, 102 00:09:22,550 --> 00:09:30,680 we have the sender, and on the right, we have the receiver. The sender wants to send 6656 103 00:09:30,680 --> 00:09:38,250 6656 bytes of data, but it's buffer size - and it's the same on the receiving end - 104 00:09:38,330 --> 00:09:42,550 the buffer size is only 2048 bytes. 105 00:09:42,590 --> 00:09:49,040 So we're going to have to send this data in three different batches, or let me check - 106 00:09:49,070 --> 00:09:52,870 it's going to be even more than three batches. 107 00:09:52,970 --> 00:09:55,100 Let's run it and see what happens. 108 00:09:55,130 --> 00:10:02,570 I'm going to press "start" and then I'm going to press "pause" right away to explain what's going on. All 109 00:10:02,560 --> 00:10:03,200 right, 110 00:10:03,300 --> 00:10:09,120 So the sender puts 2048 bytes to buffer. 111 00:10:09,120 --> 00:10:16,880 Now, sender's buffer is full. And we want to transmit that data to the receiving end. 112 00:10:16,890 --> 00:10:17,850 Let's resume. 113 00:10:22,400 --> 00:10:22,990 OK, 114 00:10:23,010 --> 00:10:29,130 at this point, the receiving end has received all of this data. 115 00:10:29,130 --> 00:10:38,850 So now the receiver buffer is full. Sender's buffer is also still full, and it's going to remain full 116 00:10:38,940 --> 00:10:46,910 until it receives the acknowledgement that the receiver has received the sent data. 117 00:10:46,920 --> 00:10:53,060 Also notice that the application hasn't read any data yet - 118 00:10:53,070 --> 00:10:54,660 it's still in the buffer. 119 00:10:54,660 --> 00:11:01,590 That's because the application reads the data in certain periods of time - so it's not always reading 120 00:11:01,590 --> 00:11:02,070 the data. 121 00:11:02,070 --> 00:11:08,270 It's not just flowing through the buffer - application is going to read the data from the buffer 122 00:11:08,340 --> 00:11:14,870 only when the buffer is full, and when the application actually wants to read that data. 123 00:11:15,210 --> 00:11:17,200 Let's see what happens next. 124 00:11:17,220 --> 00:11:23,010 We're going to resume and I'm going to hit "pause" right here. 125 00:11:23,010 --> 00:11:23,700 All right. 126 00:11:23,700 --> 00:11:32,430 So in this moment right here, the sender received an acknowledgement that says we received your 2048 127 00:11:32,420 --> 00:11:34,270 2048 bytes. 128 00:11:34,350 --> 00:11:37,080 You can send the next batch now. 129 00:11:37,140 --> 00:11:44,400 Now, I'm not going to discuss these "windows" right now - it just means that the receiving 130 00:11:44,400 --> 00:11:49,320 buffer is full and that it can't receive any more data. 131 00:11:49,320 --> 00:11:54,950 So this pretty much means "don't send any bytes yet". 132 00:11:55,800 --> 00:12:02,120 So, let's just look at this moment as we have received the acknowledgement. 133 00:12:02,220 --> 00:12:12,330 So now that the sender has received this acknowledgement, they can now delete 134 00:12:12,360 --> 00:12:19,380 the data that was in the buffer and they can transfer another batch of data from the application to 135 00:12:19,380 --> 00:12:21,630 the sending buffer. 136 00:12:21,630 --> 00:12:24,000 So that's now in the sending buffer, 137 00:12:24,000 --> 00:12:32,440 let's look at what happened in the receiving buffer. The app consumed the 2048 bytes. 138 00:12:32,550 --> 00:12:35,460 So the buffer is now empty. 139 00:12:35,640 --> 00:12:42,540 And then the next message is going to - it's going to say - "OK send the next batch and this time, I 140 00:12:42,540 --> 00:12:50,130 have this many bytes available", or "I have this much space available in my buffer" 141 00:12:50,130 --> 00:12:58,950 Now what happens next is we're going to transfer the next batch of data to the receiver, and then it's 142 00:12:58,950 --> 00:13:07,530 buffer is going to become full again, and then the application is going to take over that data. 143 00:13:07,530 --> 00:13:10,490 Let me pause here to see what's going on. 144 00:13:10,860 --> 00:13:11,440 OK. 145 00:13:11,580 --> 00:13:14,720 Application consumed the next batch. 146 00:13:14,820 --> 00:13:24,120 So it's almost getting full. Now the sender is going to send the next batch - and this is actually 147 00:13:24,120 --> 00:13:25,580 an important moment. 148 00:13:25,620 --> 00:13:29,880 So the application tries to consume the data. 149 00:13:30,780 --> 00:13:31,320 Excuse me. 150 00:13:31,560 --> 00:13:38,120 So the application tried to consume the data, but there was not enough data to consume. 151 00:13:38,130 --> 00:13:45,900 This means that you can't consume data from the buffer if the buffer is not full. 152 00:13:45,900 --> 00:13:49,680 Same goes for the sender side. 153 00:13:49,680 --> 00:13:59,580 So you can't really send the data if the buffer is not full yet, and there's still some data left in 154 00:13:59,580 --> 00:14:00,270 the application. 155 00:14:00,270 --> 00:14:08,490 So we're going to have to wait for the buffer to get fulfilled - or to to have the maximum number of bytes 156 00:14:08,520 --> 00:14:16,860 that it's supposed to have for it to be able to send the data over to the other side of the application. 157 00:14:16,890 --> 00:14:22,840 That's actually why we use this "true" argument here. 158 00:14:22,920 --> 00:14:31,740 So because we would normally have to wait for the buffer to be filled in order for the data to be sent 159 00:14:31,740 --> 00:14:39,240 to the client, we're going to say "true", which pretty much turns on the option of flushing. 160 00:14:39,240 --> 00:14:49,530 So this says to the to the socket: doesn't matter if the buffer is full or not, flush the message - just 161 00:14:49,530 --> 00:14:51,540 send it out. 162 00:14:51,600 --> 00:15:00,480 And if you've ever used Wireshark, you can just capture some data and you're going to find some 163 00:15:00,510 --> 00:15:07,020 TCP packets that have PSH flag on - that's the "push" flag. 164 00:15:07,020 --> 00:15:10,120 It's the same thing as "auto flush" 165 00:15:10,140 --> 00:15:17,790 Now the reason why we have to use "flush" in our program is because our messages are quite short. The server 166 00:15:17,790 --> 00:15:23,160 sends a short "Welcome!", and then the client sends "Thanks!", or what was it - 167 00:15:23,280 --> 00:15:24,860 - yeah it was "Thanks!" 168 00:15:24,900 --> 00:15:29,680 So we would never fill out a buffer here. 169 00:15:29,730 --> 00:15:39,180 So anytime we use out_socket, it's automatically going to turn on this push flag, and this packet - or this 170 00:15:39,180 --> 00:15:42,220 message - is going to be pushed out of the buffer, 171 00:15:42,330 --> 00:15:50,720 even though the buffer isn't filled. In the next part of our program, we are just following the protocol. 172 00:15:50,780 --> 00:15:54,850 So "connect" - let's say this is the client - 173 00:15:54,920 --> 00:16:04,950 so the client initiates the connection, and then the server sends "Welcome!" to the client using out_socket. 174 00:16:05,180 --> 00:16:08,960 And then the client is supposed to say "Thanks!" 175 00:16:09,080 --> 00:16:10,930 Back to the server. 176 00:16:10,960 --> 00:16:15,860 So when we look at the server this is where we received this message. 177 00:16:15,860 --> 00:16:19,640 So here we receive - I'm going to add a comment here - 178 00:16:19,640 --> 00:16:20,450 Receive - 179 00:16:22,940 --> 00:16:31,500 receive "Thanks!" - in this case we know in advance what is it that the client is going to say. 180 00:16:31,650 --> 00:16:39,600 So, we're going to display what the client said. And then after that, we closed the socket ,both on the 181 00:16:39,600 --> 00:16:41,540 server and on the client. 182 00:16:41,550 --> 00:16:43,700 That's this last step. 183 00:16:43,710 --> 00:16:45,340 Disconnect. 184 00:16:45,360 --> 00:16:45,890 All right. 185 00:16:45,900 --> 00:16:48,140 Let's look at the client then. 186 00:16:48,180 --> 00:16:56,220 The only difference between the client and the server, apart from some small differences in the protocol 187 00:16:56,250 --> 00:17:06,260 part, is the socket. So, for the server - we had the server socket, and the regular socket. For the client, 188 00:17:06,260 --> 00:17:11,670 we only created the regular socket because that's all we need on the client side. 189 00:17:11,720 --> 00:17:14,440 Here we are connecting to the server. 190 00:17:14,480 --> 00:17:21,500 We gave the address of the server - and we can use 127.0.0.1 here too, 191 00:17:21,500 --> 00:17:29,110 that's going to work also. And we need to make sure that we have typed in the right port number. 192 00:17:29,240 --> 00:17:32,390 Let's run the application again to check if it works. 193 00:17:32,390 --> 00:17:43,470 So we're going to run the server first. And then I'm going to run the client. And we saw that that works. 194 00:17:43,470 --> 00:17:52,140 So this isn't much fun, since everything happens on its own. In the next lesson I'm going to add a prompt 195 00:17:52,140 --> 00:17:56,270 for the client to type in its response to the server. 196 00:17:56,300 --> 00:18:03,150 So it's going to be more interesting than this. But for now, let's just go through the code on the client 197 00:18:03,150 --> 00:18:03,810 side. 198 00:18:03,870 --> 00:18:06,000 So we've already talked about the socket. 199 00:18:06,000 --> 00:18:09,410 This is pretty simple - hopefully it's clear enough. 200 00:18:09,600 --> 00:18:15,480 And then this is just the protocol part, where we are talking with the server. We're first receiving 201 00:18:15,480 --> 00:18:22,950 the message from the server that says "Welcome", and then we print that out in the console, and then in 202 00:18:22,950 --> 00:18:30,090 the end, we are sending "Thanks" back to the server. After the communication is all finished, 203 00:18:30,090 --> 00:18:32,810 we can close the socket. 204 00:18:32,940 --> 00:18:35,510 That would be it for this exercise. 205 00:18:35,520 --> 00:18:42,240 If there's anything else that maybe is still unclear, send me a message or post your question in the 206 00:18:42,240 --> 00:18:50,670 Q&A area, and then in the next lesson we're going to make this simple program just a bit more complex. 207 00:18:50,730 --> 00:18:51,870 It's not going to be much, 208 00:18:51,870 --> 00:18:55,800 don't worry, but hopefully it will at least be more fun.