课程_ 计算机网络 实验名称 套接字编程试验
一、环境(详细说明运行的操作系统,网络平台,机器的IP地址)
CPU | Intel(R) Core(TM)2 Duo CPU P8600 |
CPU主频 | 2.40GHz 双核 |
内存 | 3.00 GB (DDR2 667 MHz) |
操作系统 | Windows 7 Ultimate |
开发语言 | Java |
JDK版本 | JDK 1.6.0_26 |
代码编写 | Eclipse IDE Indigo Release |
文档编写 | Microsoft Word 2010 |
程序测试 | Google Chrome Browser |
了解应用层和运输层的作用及相关协议的工作原理和机制。
掌握 SOCKET 编程的基本方法。
三、实验内容及步骤(包括主要流程和说明)
实验内容
编写一个支持多线程处理的 Web 服务服务端软件,要求如下:
第一级:
✧可配置 Web 服务器的 IP 地址、监听端口和主目录。
✧制作一个主页放置在主目录中,并配置 Web 服务器的IP 地址、监听端口和主目录。
✧具备完成所需功能的基本图形用户界面(GUI),并具友好性。
第二级:
✧选择合适的 Socket 编程模型,创建套接字,监听所配置的监听端口。
✧支持服务的启动和关闭。
✧具备完成所需功能的基本图形用户界面(GUI),并具 友好性。
第三级:
✧支持多线程,能够针对每一个新的请求创建新的线程。
✧在服务器端的屏幕上输出每一个请求的来源(IP 地址、端口号和 HTTP 请求命令行)
✧支持一定的异常情况处理能力。
✧具备完成所需功能的基本图形用户界面(GUI),并具友好性。
第四级:
✧能够处理 HTTP 请求以及定位相应的 HTML 文件。
✧向客户端发送响应报文。
✧对于无法成功定位文件的请求,根据错误原因,作相应 错误提示。
✧在服务器端的屏幕上能够输出对每一个请求处理的结果。
✧具备完成所需功能的基本图形用户界面(GUI),并具 友好性
第五级:
✧支持多种类型文件(如 TXT 和 JPG 等)的发送。
✧具备简洁方便的 GUI 界面。
实验步骤
类的设计
本程序中设计了三个类,如下图所示:
图1 类的设计
class ServerCode : 主线程,实现了服务器端口的侦听,服务器接受一个客户端请求之后创建一个线程实例处理请求。
class connectThread : 子线程,从Thread类继承而来,实现了HTTP 协议的处理以及一些异常处理。
class Setting : 主界面,从JFrame类继承而来,主要用来画整个界面框架UI和处理与用户的交互。
代码编写
本程序所使用的IDE为Eclipse IDE Indigo Release,将实现代码键入编辑器中,当Eclipse提示没有错误时,如下所示:
图2 代码编写
即表示代码已经没有语法错误。
程序测试
点击按钮运行程序,可以看到整个配置界面,用户可以在配置界面设置端口,IP,主文件夹,配置界面下方还有个输出面板,用来输出每个客户端的IP,端口,以及对每个HTTP请求的处理结果,如下图所示:
图3 程序界面
首先设置端口(默认8000),设置IP地址(默认本机地址127.0.0.1),设置主目录(默认当前程序运行的目录),点击右下角应用按钮,将设置值反馈给程序,然后点击文件——启动服务,最后打开Google Chrome Browser,在地址栏输入127.0.0.1:8000/index.htm,得到如下页面:
图4 index.htm
然后 回到主目录下,可以看到主目录下的index.htm网页文件,如下图所示:
图5 目录下的index.htm
同样用Google Chrome Browser打开,可以看到如下页面:
图6 index.htm
由图4和图6可知,两个页面的内容一样,说明程序运行正常,客户端Google Chrome Browser从127.0.0.1地址和8000端口得到了所请求的页面。
在点击最小化之后,我们可以在任务栏看到最小化图标,
可以随时点击鼠标右键,打开程序主面板或者结束程序,
如右图所示:
四、实验结果
首先运行程序,配置按照默认设置,然后点击 文件—开启服务,这时服务器已经运行起来,打开Google Chrome Browser,在地址栏输入127.0.0.1:8000 /index.htm,可以得到主目录下的index.htm文件并显示在浏览器中,如图图4所示,然后观察服务器端,我们可以看到服务器记录了每个HTTP请求命令行以及每个HTTP请求的来源IP地址和端口,并把对每个HTTP请求的处理结果显示在输出框中,如下图所示:
图7 http请求处理
然后我们试图修改端口地址和IP地址,程序会在用户第一次试图修改IP地址时提示用户只能输入当前已连接的网络的IPv4地址。
当用户试图在服务正在运行的情况下修改端口和IP地址或者主目录时,程序都会给出提示,如下图所示:
图8 修改ip与端口地址
然后我们点击文件—关闭服务,然后点右下角的应用按钮,在更改配置之后,点击文件—开启服务,然后我们在Google Chrome Browser中输入222.20.103.127/index.htm,得到如下页面:
图9 修改ip之后的index.htm
说明程序成功地修改了端口地址和IP地址,然后更改主目录如下:
图10 修改主文件目录
重新启动服务,在浏览器中输入222.20.103.127:800/index.htm可以得到如下页面
图11 修改主目录后的 soso.htm
打开S:\\Users\\RooneyMC下的index.htm文件 如下图所示:
图12 保存在S:\\Users\\RooneyMC的index.htm
由图11和图12可知,我们的程序可以完成主目录的改变,也可以完成JPG等文件的传送。
再观察服务器端,可以看到服务器已经将所有的HTTP请求命令行和相应的处理结果显示在输出框中。如下图所示:
图13 HTTP请求响应与处理
五、实验中的问题及心得
实验中最后两个类之间的通信有些问题,不能即时将用户与服务器的交互结果在程序中更新,比如用户改变主目录,按下应用按钮之后,应用按钮的响应事件要涉及到一些全局参数的变更,这些全局参数在其他类中要实时的更新。最终的解决办法是在UI类中定义一个public布尔变量,然后在其他类中循环检测这个布尔变量的值,一旦用户的操作改变了布尔变量的值,就可以让全局参数在其他类中得到更新。
过去只是有过Android编程的经历,还没有Socket编程的概念,通过这次Socket编程的网络实验,让我更加清楚了计算机网络应用层的HTTP协议,以及主机与服务器之间通信的原理,一定程度上也提高了自己的自主学习的能力。
以往的编程语言的学习并没有多少投入到实际应用中,而是为了考试而去背知识点,这次的实验让我对Java的编程方法有了更深入的理解。
这次实验对于我在Java和网络通信的知识的领悟又抬高了一个台阶。
附录:
ServerCode.java(主线程)
import java.io.*;
import java.net.*;
import java.net.InetAddress;
import javax.swing.JOptionPane;
public class ServerCode
{
// Main method
public static void main(String[] args) throws IOException
{
// Create a server socket
final Setting stt = new Setting();
int i = 0;
// Start listening for connections on the server socket
ServerSocket serverSocket = null;
Socket connectToClient = null;/*= serverSocket.accept();*/
try
{
while (true) {
if (!stt.ModFlag) {
JOptionPane.showMessageDialog(null, "请先设置好ip和端口", "Error", 0);
continue;
}
if (!stt.StFlag && null != serverSocket) {
serverSocket.close();
serverSocket = null;
System.gc();
// continue;
}
if (stt.StFlag && null == serverSocket) {
serverSocket = new ServerSocket(stt.Port, -1, InetAddress.getByAddress(stt.ip));
// serverSocket = new ServerSocket(stt.Port, -1, InetAddress.getByAddress(byteip));
}
if (null != serverSocket) {
if (stt.zero) {
i = 0;
stt.zero = false;
}
connectToClient = serverSocket.accept();
new connectThread(connectToClient, i, stt.sltFile, stt.output).start();
i++;
}
}
}
catch(IOException ex)
{
System.err.println(ex);
}
finally {
serverSocket.close();
serverSocket = null;
connectToClient.close();
}
}
}
Setting.java(UI)
import java.awt.*;
import java.io.*;
import java.net.InetAddress;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.*;
public class Setting extends JFrame {
private JPanel contentPane;
public JTextField port;
public JTextField IpAdress;
public JTextField Directory;
private JButton btnChooseFolder;
public JFileChooser Folder;
public String sltFile;
private TrayIcon trayIcon; // 托盘图标
private SystemTray tray; // 本操作系统托盘的实例
/*菜单*/
public JMenu File;
private JMenu About;
public JTextArea output;
public JButton btnOk;
public JButton btnCancel;
public boolean ModFlag = true;
public boolean StFlag = false;
public boolean zero = false;
private boolean FirstClicked = true;
public int Port = 8000;
public byte[] ip = {(byte)127, (byte)0, (byte)0, (byte)1};
private JButton button;
/**
* Create the frame.
*/
public Setting() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setTitle("Setting");
setBounds(100, 100, 600, 450);
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
File = new JMenu("\文\件");
menuBar.add(File);
JMenuItem Startup = new JMenuItem("\启\动\服\务");
Startup.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (StFlag) {
JOptionPane.showMessageDialog(null, "服务器已经在运行", "提示", 1);
return;
}
StFlag = true;
}
});
File.add(Startup);
JMenuItem Turnoff = new JMenuItem("\关\闭\服\务");
Turnoff.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (!StFlag) {
JOptionPane.showMessageDialog(null, "服务器未运行", "提示", 1);
return;
}
StFlag = false;
}
});
File.add(Turnoff);
JMenuItem quit = new JMenuItem("\退\出");
quit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
File.add(quit);
About = new JMenu("\关\于");
About.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
JOptionPane.showMessageDialog(null, "基于Java的web服务器", "About", 1);
}
});
menuBar.add(About);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new FormLayout(new ColumnSpec[] {
FormFactory.UNRELATED_GAP_COLSPEC,
ColumnSpec.decode("8px:grow"),
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("max(19dlu;default):grow"),
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("max(12dlu;default)"),
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("16px"),
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("62px"),
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("31px:grow"),
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("47px"),
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("66px"),
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("87px"),
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("81px"),
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("default:grow"),
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("39px"),},
new RowSpec[] {
FormFactory.RELATED_GAP_ROWSPEC,
RowSpec.decode("max(14dlu;default)"),
FormFactory.UNRELATED_GAP_ROWSPEC,
RowSpec.decode("23px"),
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
RowSpec.decode("max(20dlu;default):grow"),
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
RowSpec.decode("max(9dlu;default)"),
FormFactory.RELATED_GAP_ROWSPEC,
RowSpec.decode("max(17dlu;default)"),
FormFactory.RELATED_GAP_ROWSPEC,
RowSpec.decode("max(16dlu;default):grow"),
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,}));
JLabel lblPort = new JLabel("Port");
lblPort.setForeground(Color.BLUE);
contentPane.add(lblPort, "2, 8, 4, 1, center, center");
port = new JTextField();
contentPane.add(port, "8, 8, 3, 1, fill, center");
port.setColumns(10);
port.setText("" + Port);
JLabel label = new JLabel("(1024-65535)");
label.setForeground(Color.GRAY);
contentPane.add(label, "12, 8, 3, 1");
JLabel lblIpAddress = new JLabel("IP Address");
lblIpAddress.setForeground(Color.BLUE);
contentPane.add(lblIpAddress, "16, 8, 2, 1, fill, center");
IpAdress = new JTextField();
IpAdress.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
if (FirstClicked) {
JOptionPane.showMessageDialog(null, "请修改为本机的ip地址,可在控制台中输入ipconfig得到", "提示", 1);
FirstClicked = false;
}
}
});
contentPane.add(IpAdress, "18, 8, 3, 1, fill, center");
IpAdress.setColumns(10);
try {
IpAdress.setText(InetAddress.getByAddress(ip).toString().substring(1)); /* 去掉前面的/ */
} catch (Exception e) {
e.printStackTrace();
}
JLabel lblMainFolder = new JLabel("Main Folder");
lblMainFolder.setForeground(Color.BLUE);
contentPane.add(lblMainFolder, "2, 10, 4, 1, center, center");
Directory = new JTextField();
contentPane.add(Directory, "8, 10, 11, 1, fill, center");
Directory.setColumns(10);
Directory.setEditable(false);
try {
sltFile = new File(".").getCanonicalPath();
Directory.setText(sltFile);
}
catch(IOException e) {
e.printStackTrace();
}
btnChooseFolder = new JButton("Choose");
btnChooseFolder.setForeground(Color.MAGENTA);
btnChooseFolder.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (StFlag) {
JOptionPane.showMessageDialog(null, "服务器正在运行中,请关闭服务后再修改", "Error", 0);
return;
}
Folder = new JFileChooser();
Folder.setCurrentDirectory(new java.io.File("."));
Folder.setDialogTitle("Select a Folder");
Folder.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
Folder.setAcceptAllFileFilterUsed(false);
if (Folder.showOpenDialog(btnChooseFolder) == JFileChooser.APPROVE_OPTION) {
sltFile = Folder.getSelectedFile().toString();
Directory.setText(sltFile);
}
}
});
contentPane.add(btnChooseFolder, "20, 10, center, fill");
output = new JTextArea();
output.setWrapStyleWord(true);
output.setLineWrap(true);
output.setEditable(false);
JScrollPane scrollPane = new JScrollPane(output);
contentPane.add(scrollPane, "5, 14, 18, 11, fill, fill");
btnOk = new JButton("\应\用");
btnOk.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (StFlag) {
JOptionPane.showMessageDialog(null, "服务器正在运行中,请关闭服务后再修改", "Error", 0);
return;
}
//get the Port
try {
Port = Integer.parseInt(port.getText());
if (Port < 1024) {
JOptionPane.showMessageDialog(null, "The Port is Invalid", "Error", 0);
port.selectAll();
port.requestFocus();
ModFlag = false;
return;
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
//get the IP Address
String iptp = IpAdress.getText().trim();
if (!IsIpValid(iptp)) {
JOptionPane.showMessageDialog(null, "The IP Address is Invalid","Error", 0);
IpAdress.selectAll();
IpAdress.requestFocus();
ModFlag = false;
return;
}
ConvertStrToIP(ip, iptp);
ModFlag = true;
}
});
button = new JButton("\清\除\输\出");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
output.setText("");
if (!zero) {
zero = true;
}
}
});
contentPane.add(button, "7, 26, 4, 1");
contentPane.add(btnOk, "18, 26, center, center");
/*JButton */btnCancel = new JButton("\取\消");
btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
setVisible(false);
}
});
contentPane.add(btnCancel, "20, 26, center, center");
tray = SystemTray.getSystemTray(); // 获得本操作系统托盘的实例
Toolkit kit=Toolkit.getDefaultToolkit();
Image image=kit.getImage( );
setIconImage(image);
PopupMenu pop = new PopupMenu(); // 构造一个右键弹出式菜单
final MenuItem show = new MenuItem("open");
final MenuItem exit = new MenuItem("exit");
pop.add(show);
pop.add(exit);
trayIcon = new TrayIcon(image, "Server", pop);//实例化托盘图标
//为托盘图标监听点击事件
trayIcon.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if(e.getClickCount()== 2)//鼠标双击图标
{
//tray.remove(trayIcon); // 从系统的托盘实例中移除托盘图标
setExtendedState(JFrame.NORMAL);//设置状态为正常
setVisible(true);//显示主窗体
}
}
});
//选项注册事件
ActionListener al2=new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//退出程序
if(e.getSource()==exit)
{
System.exit(0);//退出程序
}
//打开程序
if(e.getSource()==show)
{
setExtendedState(JFrame.NORMAL);//设置状态为正常
setVisible(true);
}
}
};
exit.addActionListener(al2);
show.addActionListener(al2);
try {
tray.add(trayIcon); // 将托盘图标添加到系统的托盘实例中
}
catch(AWTException ex) {
ex.printStackTrace();
}
setVisible(true);
}
public boolean IsIpValid(String strIp) {
//判断是否是空串
if (strIp.isEmpty()) {
return false;
}
//判断是否以数字开头
if (!Character.isDigit(strIp.charAt(0))) {
return false;
}
String[] ip4 = strIp.split("\\\\.");
//判断是否为4块
if (ip4.length != 4) {
return false;
}
//判断每块是否都大于0且小于256
try {
for (int i = 0; i < ip4.length; i++) {
if (Integer.parseInt(ip4[i]) < 0 || Integer.parseInt(ip4[i]) > 255) {
return false;
}
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
return true;
}
public void ConvertStrToIP(byte[] ip, String strIp) {
String[] ip4 = strIp.split("\\\\.");
try {
for (int i = 0; i < ip4.length; i++) {
ip[i] = (byte)Integer.parseInt(ip4[i]);
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
connectThread.java(子线程)
import java.net.InetAddress;
import java.net.Socket;
import java.util.StringTokenizer;
import java.io.*;
import javax.swing.JTextArea;
public class connectThread extends Thread {
final String CRLF = "\\r\\n";
private Socket client;
private int counter;
PrintStream outstream;
BufferedReader instream;
String Folder;
JTextArea output;
public connectThread(Socket skt, int count, String MainFolder, JTextArea output) {
client = skt;
counter = count;
this.output = output;
Folder = new String(MainFolder);
try {
outstream=new PrintStream(client.getOutputStream());
instream=new BufferedReader(new InputStreamReader(client.getInputStream()));
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
try {
InetAddress addr = client.getInetAddress();
String destIP=addr.toString(); //客户机IP地址
int destport=client.getPort(); //客户机端口号
String hostName = addr.getCanonicalHostName();
output.append("Connection "+counter+":connected to "+destIP+" on port "+destport+
"Client HostName:" + hostName + "." + CRLF);
processRequest(counter);
} catch (Exception e) {
e.printStackTrace();
}
}
private void processRequest(int num) throws Exception {
while (true) {
String headerLine = instream.readLine();
if (null == headerLine) {
break;
}
if (headerLine.equals("\\r\\n") || headerLine.equals("")) {
break;
}
// 完成回应消息
String ServerLine = "";
String StatusLine = null;
String ContentTypeLine = null;
String EntityBody = null;
String ContentLengthLine = "error";
boolean fileExists = true;
//打开所请求的文件
FileInputStream fis = null;
StringTokenizer s = new StringTokenizer(headerLine);
String temp = s.nextToken(); //解析消息
if (headerLine.startsWith("POST ") || headerLine.startsWith("HEAD ")) {
StatusLine = "HTTP/1.0 501 Not Implemented" + CRLF;
ContentTypeLine = "text/html";
EntityBody = "" + "
"
501 Not Implemented" + " + CRLF";
outstream.write(StatusLine.getBytes());
outstream.write(ServerLine.getBytes());
outstream.write(ContentTypeLine.getBytes());
outstream.write(ContentLengthLine.getBytes());
outstream.write(CRLF.getBytes());
outstream.write(EntityBody.getBytes());
output.append("STATUS request " + num + ": " + "the request not implemented!" + CRLF);
}
if (headerLine.startsWith("GET")) {
if (temp.equals("GET")) {
output.append("request " + num + ": " + headerLine + CRLF);
String fileName = s.nextToken();
if (!Folder.endsWith("\\\\")) {
Folder += "\\\\";
}
String filename1 = Folder + fileName.substring(1);
try {
fis = new FileInputStream(filename1); //文件输出流
} catch (Exception e) {
fileExists = false;
output.append("STATUS request " + num + ": " + "file not found-->:" + filename1 + CRLF);
}
if (fileExists) {
StatusLine = "HTTP/1.0 200 OK" + CRLF;
ContentTypeLine = "Content-Type: " + contentType(filename1) + CRLF;
ContentLengthLine = "Content-Length: " + (new Integer(fis.available())).toString() + CRLF;
}
else {
StatusLine = "HTTP/1.0 404 Not Found" + CRLF;
ContentTypeLine = "text/html";
EntityBody = "" + "
"
404 Not Found" + fileName + ".html + CRLF";}
//发送到服务器信息
outstream.write(StatusLine.getBytes());
outstream.write(ServerLine.getBytes());
outstream.write(ContentTypeLine.getBytes());
outstream.write(ContentLengthLine.getBytes());
outstream.write(CRLF.getBytes());
if (fileExists) {
sendBytes(fis, outstream);
fis.close();
output.append("STATUS request " + num + ": " + "Succeed!" + CRLF);
}
else {
outstream.write(EntityBody.getBytes());
}
}
else {
StatusLine = "HTTP/1.0 400 Bad Request" + CRLF;
ContentTypeLine = "text/html";
EntityBody = "" + "
"
400 Bad Request" + " + CRLF";outstream.write(StatusLine.getBytes());
outstream.write(ServerLine.getBytes());
outstream.write(ContentTypeLine.getBytes());
outstream.write(ContentLengthLine.getBytes());
outstream.write(CRLF.getBytes());
outstream.write(EntityBody.getBytes());
output.append("STATUS request " + num + ": " + "the request is invalid!" + CRLF);
}
}
}
try {
outstream.close();
instream.close();
} catch (Exception e) {
e.printStackTrace();
}
finally {
client.close();
}
}
private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception {
//创建一个 1K buffer
byte[] buffer = new byte[1024];
int bytes = 0;
//将文件输出到套接字流中
while ((bytes = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytes);
}
}
private static String contentType(String fileName) {
if (fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
return "fileName";
}
}