目录
实验内容
实验步骤
实验一
1.获取本机IP地址
2. 获取指定网站IP地址
3. 使用URL类下载网页并统计大小
实验二
1.使用TCP连接和Socket类实现C/S通信
2.使用UDP连接来编写数据报通信程序
实验三
1.利用TCP连接实现文件传输
我们可以使用Java中的InetAddress类来获得本机地址,用getLocalHost函数将本机地址传输到建立的locAdd对象当中,并用对象调用getHostAddress和getHostName这两个函数来获取存取在locAdd中的本机IP地址和本机名称。
package demo;
import java.net.InetAddress ;
public class InetAddressDemo {
public static void main(String[] args)throws Exception {
InetAddress locAdd = null ;
locAdd = InetAddress.getLocalHost() ;
System.out.println("本机IP地址:"+locAdd.getHostAddress()); //获取本机的IP地址并打印
System.out.println("本机名称:"+locAdd.getHostName()); //获取本机的名称并打印
}
}
首先使用一个String类型的对象来存放网站名称。创建一个InetAddress的对象数组addresses,用于存放获取的所有IP地址。再使用getAllByName函数,来获取指定网站的所有IP地址,并且存放在addresses对象数组当中。最后输出。
package demo;
import java.net.InetAddress ;
public class InetAddressDemo2 {
public static void main(String[] args)throws Exception {
//获取网站www.baidu.com的IP地址
String host = "www.baidu.com";
InetAddress addresses [] = null;
addresses=InetAddress.getAllByName(host);
//获取网站www.csdn.net的IP地址
for (InetAddress address : addresses)
System.out.println(address);
host = "www.csdn.net";
addresses=InetAddress.getAllByName(host);
//获取网站www.csdn.net的IP地址
for (InetAddress address : addresses)
System.out.println(address);
}
}
使用URL类创建一个对象url,并且用构造函数写入要连接的网页地址。并且用URLConnection类创建一个对象urlconnect,用于与网站进行连接。再使用openConnection函数来建立连接。
使用FileOutStream类建立输出流,将获取的信息存储到外部文件——szu.html当中。建立输入流来接受url的信息。
使用read函数从网站中读取数据并用write函数写入到文件当中。最后使用File类来进行统计文件大小,使用file.length方法函数来获取文件大小。
public class URLConnectionDemo {
public static void main(String[] args) throws Exception{
URL url = new URL("http://www.szu.edu.cn") ;
URLConnection urlconnect;
urlconnect=url.openConnection();//使用URLConnection建立url连接
FileOutputStream fout=new FileOutputStream(new File("szu.html"));
InputStream input = url.openStream() ;
int a=0;
while(a>-1) {
a=input.read();
//System.out.println(a) ;
fout.write(a);
}
File file = new File("szu.html");
System.out.println("文件大小为:"
+ new DecimalFormat("#.00").format(file.length() / 1024.00)
+ "k");
//统计下载得到网页文件的大小,并打印
}
}
首先是Server端,在Server端先使用ServerSocket类创建一个server对象,并设置其端口号为6789。使用accept方法函数来等待与客户端进行连接。
接着使用BufferedReader来获取客户端的数据。使用ServerSocket类中的getInputStream方法函数将输入流与BufferedReader连接。
在while循环中,一直将接收到的数据存放到String类中的str对象当中,并且创建一个DataOutputStream类,用于将数据发送给客户端,并建立输出流。
若str接收的数据是“exit”则向客户端发送字段“Bye\n”并且输出一个Bye后退出循环并终止服务器。
若str接收的数据是“Time”则发送当前服务器的时间。使用Calendar类来获取当前的时间,并且用SimpleDateFormat类来设置时间的输出格式,接着将当前时间用Byte格式传输给客户端,并且在服务器端也输出。
public class server {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(6789);
System.out.println("服务器启动完毕");
Socket socket=server.accept();//等待连入请求,并创建客户连接
System.out.println("创建客户连接");
BufferedReader reader;
reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//创建与套接字连接的输入流,接收信息使用BufferedReader读取。
while (true) {
String str = reader.readLine();
DataOutputStream ToClient=new DataOutputStream(socket.getOutputStream());
//如果接收到“exit”,打印"bye"
if (str.equals("exit")) {
ToClient.writeBytes("Bye\n");
System.out.println("Bye");
break;
}
//如果收到"Time",打印“服务器当前的时间为:”+实际时间
if(str.equals("Time")) {
Calendar calendar=Calendar.getInstance();
SimpleDateFormat dateformat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss ");
System.out.println("Current Server time is:"+dateformat.format(calendar.getTime()));
String str1="Current Server time is:"+dateformat.format(calendar.getTime());
ToClient.writeBytes(str1+"\n");
}
}
reader.close();
socket.close();
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端中先使用Socket类创建一个ClientSocket对象,并设置端口为6789,此时服务器端和客户端就进行了连接。接着创建一个DataOutputStream与ClientSocket的输出流进行连接,用于传送数据给服务器端。再创建一个BufferedReader用于接受服务器端的数据,同样与ClientSocket对象建立连接。
向服务器端输出Byte类型的数据“Time\n”,接下来进入一个循环。因为在实验的时候会发现服务端对客户发送的数据会先发送一个空白的数据,所以我先进入一个循环,直到接受的数据不是空白的,输出该数据并且跳出这个循环。
同理在下面发送“Bye\n”和接受数据时与上述一样。全部执行完毕后关闭输入输出流和TCP连接。
public class Client {
static String hostname=new String("localhost");
public static void main(String[] args) {
try {
Socket ClientSocket = new Socket(hostname, 6789);
//client端创建一个socket,与服务器连接
DataOutputStream out =
new DataOutputStream(ClientSocket.getOutputStream());
//创建与socket连接的输出流,定义为out
BufferedReader reader;
reader=new BufferedReader(new InputStreamReader(ClientSocket.getInputStream()));
out.writeBytes("Time\n");
while(true) {
String str=reader.readLine();
if(str.length()>0) {
System.out.println(str);
break;
}
}
out.write("exit\n".getBytes());
//reader=new BufferedReader(new InputStreamReader(ClientSocket.getInputStream()));
while(true) {
String str=reader.readLine();
if(str.length()>0) {
System.out.println(str);
}
break;
}
ClientSocket.close();
out.close();
reader.close();
} catch (UnknownHostException e) {
System.out.println("UnknownHost");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
但要运行两个程序时,先开启服务器端的程序,再开启客户端的程序。我们可以在指令台中切换运行的程序。
要特别注意的是服务器端必须在之前的程序执行结束后在开启,否则会提示端口号已被占用。
客户端中出现的前面的乱码我认为应该是汉字在从Byte转换时出现了问题,于是我改为传输英文字母再运行一遍。
服务器:
首先使用DatagramSocket类创建一个ServerSocket对象,并设置端口号为9876。
创建两个byte类型的变量数组用于接受和发送字段。
接着进入一个循环,用于一直接受数据和发送数据。
在循环当中,要先清空receiveData中原有的数据,所以使用receivedata = new byte [1024];来进行清空。使用DatagramPacket类来接收从客户端传输过来的数据,并将传输过来的数据存放到receiveData中。将数据存放到String类型的对象sentence当中。接着从recievePacket中获取客户端的IP地址和端口号,并存放在InetAddress类的IPAddress对象中和int类型的port变量中。接着将sentence中的数据字母大写,再用sendData发送给客户端。
class UDPServer {
public static void main(String args[]) throws Exception
{
DatagramSocket ServerSocket = new DatagramSocket(9876);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
String sentence;
while(true)
{
receiveData = new byte[1024];
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
ServerSocket.receive(receivePacket);
sentence = new String(receivePacket.getData());
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
System.out.println(sentence);
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, port);
ServerSocket.send(sendPacket);
//ServerSocket.close();
}
}
}
客户端:
将在控制台传输进去的数据直接传输给BufferedReader类的inFromUser对象当中。接着建立DatagramSocket类的ClientSocket,并获取本机的IP地址存放到IPAddress对象当中。与服务器端一样的创建Byte类型的数组sendData和recieveData。inFromUser中的数据传输给String类型的sentence当中,并且再转换为Byte类型,用DatagramPacket发送给服务器端。再进行接受服务器端传来的数据,并进行输出。
class UDPClient {
public static void main(String args[]) throws Exception {
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
DatagramSocket ClientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getLocalHost();
byte[ ] sendData = new byte[1024];
byte[ ] receiveData = new byte[1024];
String sentence = inFromUser.readLine();
System.out.println(sentence);
sendData = sentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
ClientSocket.send(sendPacket);
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
ClientSocket.receive(receivePacket);
String modifiedSentence =
new String(receivePacket.getData());
System.out.println("FROM Server:" + modifiedSentence);
ClientSocket.close();
}
}
运行一次
服务器端:
客户端:
运行第二次:
服务器端:
客户端:
该实验使用的是线程来处理执行命令。
在服务器端中,先是该类继承了线程接口Runnable。成员对象有静态类型的端口号和Socket类的对象s。SendFileServer方法函数是将参数的Socket与本类的Socket进行赋值,super字样是使用父类的构造函数。
在server方法函数当中,先是创建了一个Socket ss,并设置端口号。进入一个循环,先是与客户端进行连接并存放到s中,输出线程数量,在调用线程并开启。
Run方法是线程运行时要执行的程序。这里进行的操作时间test.txt文件里的数据传输到客户端的文件当中,方法与1.a)中传输数据相似。
public class SendFileServer implements Runnable{
private static final int MONITORPORT = 12345;
private Socket s ;
public SendFileServer(Socket s) {
super();
this.s = s;
}
public static void server()
{
try {
ServerSocket ss = new ServerSocket(MONITORPORT);
int i=0;
while(true)
{
i++;
Socket s = ss.accept();
System.out.println("服务器的线程"+i+"启动,与客户端1连接成功");
new Thread(new SendFileServer(s)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SendFileServer.server();
}
@Override
public void run() {
byte[] buf = new byte[100];
OutputStream os=null;
FileInputStream fins=null;
try {
os = s.getOutputStream();
String fileName = "test.txt";
System.out.println("要传输的文件为: "+fileName);
os.write(fileName.getBytes());
System.out.println("开始传输文件");
fins = new FileInputStream(fileName);
int data;
while(-1!=(data = fins.read()))
{
os.write(data);
}
System.out.println("文件传输结束");
} catch (IOException e) {
e.printStackTrace();
}finally
{
try {
if(fins!=null) fins.close();
if(os!=null) os.close();
this.s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端:
设置IP地址,本机端口号和服务器端口号。
先与服务器进行连接,创建一个输入流和输出流,分别与服务器端和文件进行连接,间服务器接收到的数据传输给文件。
public class SendFileClient {
private static final String SERVERIP = "127.0.0.1";
private static final int SERVERPORT = 12345;
private static final int CLIENTPORT = 54321;
public static void main(String[] args) {
byte[] buf = new byte[100];
Socket s = new Socket();
try {
s.connect(new InetSocketAddress(SERVERIP,SERVERPORT), CLIENTPORT);
System.out.println("与服务器连接成功");
InputStream is = s.getInputStream();
int len = is.read(buf);
String fileName = new String(buf,0,len);
System.out.println("接收到的文件为:"+fileName);
System.out.println("保存为为:"+"1"+fileName);
FileOutputStream fos = new FileOutputStream("1"+fileName);
int data;
while(-1!=(data = is.read()))
{
fos.write(data);
}
is.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
第一次运行:
服务器端:
客户端:
第二次运行:
服务器端:
客户端:
test.txt文件:
1test.txt文件: