资源描述
广州大学学生实验报告
开课学院及实验室:计算机科学与工程实验室 2014年12月05日
学院
计算机科学与教育软件学院
年级/专业/班
姓名
学号
实验课程名称
Java语言
成绩
实验项目名称
综合应用实验
指导老师
樊志平
一、 实验目的
实验十三 网络编程(1)
1. 掌握使用Socket类的属性和基本方法,
2. 掌握使用ServerSocket类的方法
实验十四 网络编程(2)
1. 掌握使用DatagramSocket类的属性和基本方法,
2. 掌握使用DatagramPacket类的方法
二、实验器材
1.MacBook Pro一台
2.操作系统:OS X Yosemite
3.编程软件:eclipse
三、实验内容及原理
实验十三 网络编程(1)
1. 掌握使用使用Socket、ServerSocket类的方法。
一.使用Socket、ServerSocket
服务器端程序设计模型
(1) 在服务器端,先创建类ServerSocket的实例对象,注册在服务器端进行连接的端口号以及允许连接的最大客户数目。
(2) 调用类ServerSocket的成员方法accept来等待客户端的连接,当有客户端与服务器端建立连接时,accept方法将返回连接通道在服务器端的套接字。通过该套接字可以与客户端进行数据通信
(3) 调用类Socket的成员方法getInputStream和getOutputStream获得该套接字所对应的输入流(InputStream)和输出流(OutputStream)
(4) 通过输入流(InputStream)和输出流(OutputStream)与客户端进行数据通信,处理从客户端获得的数据以及需要向客户端发送数据
(5) 通信完毕后,关闭输入流和输出流和套接字
客户端
(1) 创建类Socket的实例对象,与服务器建立连接,在建立实例对象时须指定服务器端的主机名和端口号,主机名和端口号必须完全匹配才能建立连接
(2) 调用类Socket的成员方法getInputStream和getOutputStream获得该套接字所对应的输入流(InputStream)和输出流(OutputStream)
(3) 通过输入流(InputStream)和输出流(OutputStream)与客户端进行数据通信,处理从客户端获得的数据以及需要向客户端发送数据
(4) 通信完毕后,关闭输入流和输出流和套接字
实验十四 网络编程(2)
1.掌握使用使用DatagramSocket、DatagramPacket类的方法。
一 使用DatagramSocket、DatagramPacket
(1) 在服务器端,先创建类DatagramSocket的实例对象,注册在服务器端进行连接的端口号。等待客户程序的请求
(2) 创建据报的缓冲区,调用DatagramPacket创建接受数据包
(3) 调用类DatagramSocket的成员方法receive来接受客户端的数据,并获取客户端IP地址和端口
(4) 创建包含发送数据和向给定IP地址和端口发送的应答数据包;
(5) 调用类DatagramSocket的成员方法send来发送数据报
(6) 通信完毕后,关闭UDPDaytimeServer并退出;
客户端
(1) 创建类DatagramSocket的实例对象
(2) 创建请求和应答缓冲区,调用DatagramPacket创建发送数据包,在创建数据包时须指定服务器端的主机名和端口号,和需要发送的数据与数据长度
(3) 调用类DatagramSocket的成员方法send来发送请求
(4) 调用类DatagramSocket的成员方法receive来接受数据报
(5) 通信完毕后,关闭输入流和输出流和套接字
四、实验过程原始数据记录
实验十三 网络编程(1)
1.使用ServerSocket编写一个时间服务器程序,它能够向客户程序发送以下格式的时间信息。
时间格式为:Sat Jan 15 10:45:20 CST 2005
(1) 服务器端
JTimeServer.java
import .*;
import java.io.*;
import java.util.*;
public class DaytimeServer{
public static void main(String[] args){
ServerSocket timeSocket;
Socket clientSocket;
OutputStream out;
Date currDate;
if(args.length<1){
System.out.println("Usage: java DaytimeServer port");
System.out.println("Example: java DaytimeServer 1234");
System.exit(-1);
}
try{
timeSocket = new ServerSocket(Integer.parseInt(args[0]));
System.out.println("时间服务器已经启动,正在侦听断口"+args[0]+"...");
try{
while(true){
clientSocket = timeSocket.accept();
try{
out = clientSocket.getOutputStream();
currDate = new Date();
out.write(currDate.toString().getBytes());
System.out.println("服务器时间[" + currDate + "]已经发送到"+
clientSocket.getInetAddress());
}finally {
clientSocket.close();
}
}
}finally {
timeSocket.close();
}
}catch(IOException ex){
System.out.println(ex);
}catch(NumberFormatException e){
System.out.println("illeagl port "+args[0]);
}
System.exit(0);
}
}
(2)客户端
DaytimeClient.java
import .*;
import java.io.*;
public class DaytimeClient{
public static void main(String[] args){
String serverName;
String serverPort="1234";
InetAddress serverAddress;
String inBuffer;
Socket daytimeSocket;
BufferedReader socketIn;
if(args.length<2){
System.out.println(
"usage: java DaytimeClient serverName serverPort");
System.out.println("Example: java DaytimeClient 127.0.0.1 1234");
}
else{
try{
serverName=args[0];
serverAddress=InetAddress.getByName(serverName);
serverPort=args[1];
System.out.println("正在连接时间服务器"+
serverAddress.toString()+" port:"+serverPort+"...");
daytimeSocket = new Socket(
serverAddress,Integer.parseInt(serverPort));
try{
daytimeSocket.setSoTimeout(5 * 1000);
socketIn=new BufferedReader(
new InputStreamReader(daytimeSocket.getInputStream()));
inBuffer = socketIn.readLine();
System.out.println("时间服务器应答: "+inBuffer);
}finally{
daytimeSocket.close();
}
}catch(IOException ex){
System.out.println(ex);
}catch(NumberFormatException e){
System.out.println("illeagl serverPort "+serverPort);
}
}
System.exit(0);
}
}
运行结果:
服务器:
客户端:
2. 使用套接字传输数据,计算机三角形面积,客户端输入三角形的三条边长,并将数据发送给服务器端,服务器端计算机三角形面积并发送给客户端
(1)客户端程序
Client.java
import .*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Client extends JFrame implements Runnable,ActionListener
{
JButton connection,computer;
JTextField inputA,inputB,inputC;
JTextArea showResult;
Socket socket=null;
DataInputStream in=null;
DataOutputStream out=null;
Thread thread;
public Client()
{
socket=new Socket();
connection=new JButton("连接服务器");
computer=new JButton("求三角形面积");
computer.setEnabled(false);
inputA=new JTextField("0",12);
inputB=new JTextField("0",12);
inputC=new JTextField("0",12);
Box boxV1=Box.createVerticalBox();
boxV1.add(new JLabel("输入边A"));
boxV1.add(new JLabel("输入边B"));
boxV1.add(new JLabel("输入边C"));
Box boxV2=Box.createVerticalBox();
boxV2.add(inputA);
boxV2.add(inputB);
boxV2.add(inputC);
Box baseBox=Box.createHorizontalBox();
baseBox.add(boxV1);
baseBox.add(boxV2);
Container con=getContentPane();
con.setLayout(new FlowLayout());
showResult=new JTextArea(8,18);
con.add(connection);
con.add(baseBox);
con.add(computer);
con.add(new JScrollPane(showResult));
computer.addActionListener(this);
connection.addActionListener(this);
thread = new Thread(this);
setBounds(100,100,360,310);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void run()
{
while(true)
{
try{
double area=in.readDouble();
showResult.append("\n三角形的面积:\n"+area);
showResult.setCaretPosition((showResult.getText()).length());
}
catch(IOException e)
{
showResult.setText("与服务器已断开");
computer.setEnabled(false);
break;
}
}
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==connection)
{
try
{
if(socket.isConnected())
{
}
else
{
InetAddress address=InetAddress.getByName("127.0.0.1");
InetSocketAddress socketAddress=new InetSocketAddress(address,4331);
socket.connect(socketAddress);
in =new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
computer.setEnabled(true);
thread.start();
}
}
catch (IOException ee){}
}
if(e.getSource()==computer)
{
try
{
double a=Double.parseDouble(inputA.getText()),
b=Double.parseDouble(inputB.getText()),
c=Double.parseDouble(inputC.getText());
if(a+b>c&&a+c>b&&b+c>a)
{
out.writeDouble(a);
out.writeDouble(b);
out.writeDouble(c);
}
else
{
inputA.setText("你输入的3个数不构成三角形");
}
}
catch(Exception ee)
{
inputA.setText("请输入数字字符");
}
}
}
public static void main(String args[])
{
Client win=new Client();
}
}
(2)服务器端程序
import java.io.*;
import .*;
import java.util.*;
public class Server
{
public static void main(String args[])
{
ServerSocket server=null;
ServerThread thread;
Socket you=null;
while(true)
{
try{
server=new ServerSocket(4331);
}
catch(IOException e1)
{
System.out.println("正在监听");
}
try{
you=server.accept();
System.out.println("客户的地址:"+you.getInetAddress());
}
catch (IOException e)
{
System.out.println("正在等待客户");
}
if(you!=null)
{
new ServerThread(you).start();
}
else
{
continue;
}
}
}
}
class ServerThread extends Thread
{
Socket socket;
DataOutputStream out=null;
DataInputStream in=null;
String s=null;
ServerThread(Socket t)
{
socket=t;
try {
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
}
catch (IOException e)
{}
}
public void run()
{
while(true)
{
double a=0,b=0,c=0,area=0;
try{
a=in.readDouble();
b=in.readDouble();
c=in.readDouble();
double p=(a+b+c)/2.0;
area=Math.sqrt(p*(p-a)*(p-b)*(p-c));
out.writeDouble(area);
}
catch (IOException e)
{
System.out.println("客户离开");
break;
}
}
}
}
运行结果:
服务器:
客户端:
实验十四 网络编程(2)
1.使用DatagramSocket编写一个时间服务器程序,它能够向客户程序发送以下格式的时间信息。
时间格式为:Sat Jan 15 10:45:20 CST 2005
算法提示:
打开一个数据报DatagramSocket;
开始循环:
创建客户程序请求数据报的缓冲区并等待请求;
当接收到请求时获取发送者(即客户程序)的IP地址和端口;
创建包含当前日期和时间信息,可向给定IP地址和端口发送的应答数据包;
发送上述应答数据包;
结束循环;
关闭UDPDaytimeServer并退出;
(1)服务器端程序
import .*;
import java.io.*;
import java.util.*;
public class UDPDaytimeServer{
public static void main(String[] args){
DatagramSocket timeSocket;
Date currDate;
byte[] inBuffer;
byte[] outBuffer;
DatagramPacket request;
DatagramPacket reply;
InetAddress clientAddress;
int clientPort;
if(args.length<1){
System.out.println("Usage: java UDPDaytimeServer port");
System.out.println("Example: java UDPDaytimeServer 1234");
System.exit(-1);
}
try{
timeSocket=new DatagramSocket(Integer.parseInt(args[0]));
System.out.println("时间服务器已经启动,正在侦听断口"+args[0]+"...");
try{
while(true){
inBuffer=new byte[1];
request=new DatagramPacket(inBuffer,inBuffer.length);
// 等待客户程序的请求
timeSocket.receive(request);
// 获得客户程序的地址和端口
clientAddress = request.getAddress();
clientPort = request.getPort();
System.out.println("接受来自" + clientAddress +
", port " + clientPort + "的时间服务请求.");
// 创建并发送应答数据
currDate = new Date();
outBuffer = currDate.toString().getBytes();
reply = new DatagramPacket(outBuffer, outBuffer.length,
clientAddress, clientPort);
timeSocket.send(reply);
}
}finally{
timeSocket.close();
}
}catch(IOException ex){
System.out.println(ex);
}catch(NumberFormatException e){
System.out.println("illeagl port "+args[0]);
}
System.exit(0);
}
}
(1)客户端程序:UDPDaytimeClient
import .*;
import java.io.*;
public class UDPDaytimeClient {
public static void main(String[] args) {
String host;
InetAddress hostAddress;
byte[] outBuffer=new byte[1];
byte[] inBuffer=new byte[512];
DatagramPacket request;
DatagramPacket reply;
DatagramSocket timeSocket;
if(args.length<2){
System.out.println("usage: java UDPDaytimeClient serverName serverPort");
System.out.println("Example: java UDPDaytimeClient 127.0.0.1 1234");
}else{
try{
host=args[0];
hostAddress=InetAddress.getByName(host);
System.out.println("正在取得"+ hostAddress.toString()+"的日期...");
timeSocket=new DatagramSocket();
// 创建请求和应答缓冲区
request = new DatagramPacket(outBuffer, outBuffer.length,
hostAddress, Integer.parseInt(args[1]));
reply = new DatagramPacket(inBuffer, inBuffer.length);
// 发送请求并读取应答
try{
timeSocket.setSoTimeout(5*1000);
timeSocket.send(request);
timeSocket.receive(reply);
System.out.print("时间服务器应答:"+
new String(inBuffer, 0, reply.getLength()));
}finally{
timeSocket.close();
}
}catch(IOException ex){
System.out.println(ex);
}catch(NumberFormatException e){
System.out.println("illeagl serverPort "+args[1]);
}
}
System.exit(0);
}
}
运行结果:
服务器:
客户端:
五、实验结果及分析
单纯的做上面的实验并不能真正学到多少,因为通常java都是做服务端的,跟其他不同平台进行数据通信,于是我为了加深对Socket的了解,我特意为iPhone写了个客户端,服务端依然用java,测试它们之间数据的传送。
运行结果如下:
Iphone端:
连接后接收到来自java服务端的字符串。
点击计算,发送边长给服务器,并获取计算结果。
服务端:
在编写iPhone端的Socket客户端期间遇到了很大问题。
Java服务端识别不了iPhone端发送的字符串。于是各种谷歌搜索,发现问题如下,原来java的readUTF读取的字符跟objective-c 的并不完全相同。
但是没有问题是解决不了的,最后还是解决了这个奇怪的问题。
展开阅读全文