1. 本章学习总结
2. 书面作业
1. 网络基础
1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同?
1.2 telnet bbs.newsmth.net,上面这条命令连接的是远程主机的什么端口号?
1.3 telnet cec.jmu.edu.cn 80,尝试回答:你从屏幕看到一些什么内容?返回的内容是不是cec.jmu.edu.cn的主页内容?尝试使用GET /index HTTP/1.0命令,会返回什么?详见实验任务书题目1。
1.4 启动ConnectionWatcher, 然后启动若干个可以联网的程序(如QQ, telnet,浏览器等),查看本机上有什么程序联网,使用了什么端口?QQ占用了什么端口和那些远程IP进行交互,这些IP分布地在那里?使用了什么协议进行通信?
1.5 编写网络程序必不可少的几个信息是什么?
1.1
从上比较发现,在数据包的接发时间上二者有着较大的区别。cec.jmu.edu.cn是内网,在LAN中传输速度基本只取决于物理设备的传输速度,外网的话考虑到学校的接入带宽以及使用人数等,自然速度不如内网。
1.2
Telnet默认端口为23
1.3
输入后回车,接着按ctrl+]进入Telnet界面
报405错误,不能用GET方法访问?再尝试一下
不知为啥就行了。。
用在线HTTP命令模拟结果:
这里结果是报301,链接转移???
反正结果就是返回页面的html代码,看得懂的自然就知道是个网页,至于报错问题要再研究研究。
1.4
对QQ进行交互的IP进行查找
这个我猜大概是腾讯那边保存信息的服务器,当发给不在线的用户信息或文件时采用TCP协议传输,先保存在服务器上。
还有一个TCP协议连接的是这个IP地址:
讲道理这个我是没懂。。。
而一般的用户之间的通信采用的是UCP协议传输数据,由于UCP能穿透绝大多数的代理服务器,而且基于我国的网络状况,QQ选择UCP而不是TCP作为主要传输协议。
1.5
通信方式,协议类型,端口号等等
2. 编写TCP客户端程序
2.1 参照SocketTest.java编写一个简单的连接远程服务器小程序Client.java,可以接收并显示服务器发送的信息。启动时需要首先在控制台指定远程主机IP与端口号。(截图,出现自己学号)
2.2 将程序中的网址改成bbs.newsmth.net,端口号改为23,再次观察返回结果?尝试执行telnet bbs.newsmth.net 23,对比返回结果。
2.3 将程序中的网址改成cec.jmu.edu.cn,端口号改为80进一步观察返回结果。没有任何返回结果,为什么?怎么操作
2.4 启动网络调试助手,将其设置为TCP Server,并启动,如下图所示
2.1
//201521123055
Scanner sc=new Scanner(System.in);
String host;
int port;
host=sc.next();
port=sc.nextInt();
try
{
Socket s = new Socket(host, port);
try
{
InputStream inStream = s.getInputStream();
Scanner in = new Scanner(inStream);
while (in.hasNextLine())
{
String line = in.nextLine();
System.out.println(line);
}
}
finally
{
s.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
2.2
丑的不忍直视。。出现乱码大概是编码问题
2.3
需要模拟HTTP请求得到响应才有输出。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.ArrayList;
//201521123055
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("cec.jmu.edu.cn", 80);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
StringBuffer buffer = new StringBuffer();
buffer.append("GET http://cec.jmu.edu.cn:80 HTTP/1.1\r\n");
buffer.append("Host: cec.jmu.edu.cn:80\r\n");
buffer.append("UserAgent: IE8.0\r\n");
buffer.append("Connection: Keep-Alive\r\n");
buffer.append("\r\n");
writer.write(buffer.toString());
writer.flush();
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
ArrayList<String> result=new ArrayList<>();
while((line=reader.readLine())!=null){
result.add(line);
}
for(int i=0;i<result.size();i++)
{
System.out.println(result.get(i));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果:
HTTP/1.1 200 OK
Date: Sat, 20 May 2017 07:04:23 GMT
Server: VAppServer/6.0.0
X-Frame-Options: SAMEORIGIN
Vary: User-Agent,Accept-Encoding
Content-Type: text/html;charset=UTF-8
Content-Length: 1361
Set-Cookie: JSESSIONID=12DA269DB605E1D31115D7D6AA74960B; Path=/; HttpOnly
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Language: zh-CN
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<link rel="stylesheet" Content-type="text/css" href="/system/resource/code/auth/auth.css" />
<title>系统提示</title>
</head>
<body leftmargin="0" topmargin="0">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="prompt">
<div class="promptOne">系统发生错误</div>
<div class="promptTwo">抱歉</div>
<div class="promptThere">可能是由下列问题导致的:</div>
<p>当前页面发生错误, 请联系管理员(错误标识码:RAD65),或稍后重试</p>
<br><br>
<input type="button" onclick="javascript:history.go(-1);" value="返回上一页">
<input type="button" onclick="javascript:window.opener=null;window.open('','_self');window.close();" value="关闭当前窗口">
</td>
</tr>
</table>
</body>
</html>
2.4
以end为结束符
2.5
之前是模拟GET请求,需要交互的话采用POST请求。
3. ServerSocket与TCP服务器
3.1 简易单线程MenuServer,题目3.1-3.4。(关键代码及运行截图,包含学号)可以使用网络调试助手,将其设置为TCP Client(IP与端口填你的MenuServer的IP与端口),连接你的MenuServer。其中的文件搜索功能为选做。
3.2 多线程MenuServer(截图证明你这个是多线程服务器,使用telnet连接)。
3.1
//201521123055
public void menu(Socket socket,String order,PrintWriter writer)
{
writer.println("1.显示服务器当前时间 ");
writer.println("2.您的IP ");
writer.println("3.文件搜索 ");
writer.println("4.退出菜单");
BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while(!(line=in.readLine()).equals("quit"))
{
if(line.equals("1"))
{
Date date=new Date();
DateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time=format.format(date);
writer.println(time);
}
else if(line.equals("2"))
{
String ip = InetAddress.getLocalHost().getHostAddress();
writer.println(ip);
}
else if(line.equals("4"))
{
return;
}
}
}
3.2
//201521123055
ServerSocket serverSocket=new ServerSocket(8190);
while(n<3)
{
Socket socket=serverSocket.accept();
Runnable runnable=new MenuServer();
Thread thread=new Thread(runnable);
n++;
}
4. UDP服务器
4.1 改造3.1或3.2,将其改造成基于UDP的MenuServer。(运行界面代码截图,包含学号)。可以使用网络调试助手,将其设置为UDP,要填本机IP与端口也要填远程服务器的IP与端口。
4.1
//201521123055
try {
InetAddress address = InetAddress.getLocalHost();
int port = 8190;
DatagramSocket socket = new DatagramSocket(port, address);
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String getMsg = new String(buf, 0, packet.getLength());
System.out.println("客户端发送的数据为:" + getMsg);
Menu();
BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while(!(line=in.readLine()).equals("quit"))
{
if(line.equals("1"))
{
Date date=new Date();
DateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time=format.format(date);
writer.println(time);
}
else if(line.equals("2"))
{
String ip = InetAddress.getLocalHost().getHostAddress();
writer.println(ip);
}
else if(line.equals("4"))
{
return;
}
InetAddress clientAddress = packet.getAddress();
int clientPort = packet.getPort();
SocketAddress sendAddress = packet.getSocketAddress();
String feedback = "Received";
byte[] backbuf = feedback.getBytes();
DatagramPacket sendPacket = new DatagramPacket(backbuf, backbuf.length, sendAddress);
socket.send(sendPacket);
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
5. 论述题:网络程序与流
5.1 前面编写的程序用到了大量的流的相关知识。简述,编写网络程序时应当选择什么样的流?Java网络编程、流之间的关系。场景如:简单的文字聊天、文件传输、应用层协议服务器,如QQ、聊天室、网络游戏。
程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。所有文件的储存是都是字节的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件时,也是一个字节一个字节地读取以形成字节序列。字符流予以修饰。
6. 代码阅读
6.1 修改程序,在GUI界面中某个地方显示自己的学号,然后运行该程序(截图、出现学号)。简述这个程序的主要功能。
6.2 画出源代码的结构图(各个类的依赖关系)。并简要说明各个类的功能。
6.3 简述这个程序有什么不足之处及改进方法.
6.1
完成服务端与客户端的交互。
6.2
客户端界面,客户端监听,客户端线程读取
服务端界面,服务端监听,服务端线程读取
6.3
没有很好地表明信息来源,服务端发送消息显示无换行(或根本不用显示在服务端)