Java基础-网络编程
网络编程2
1、网络编程(TCP-上传图片)
需求:上传图片 客户端:
(1)、服务端点
(2)、读取客户端已有的图片数据。
(3)、通过socket输出流将数据发给服务端
(4)、读取服务端反馈信息。
(5)、关闭资源。
测试代码:
import java.io.*;
import java.net.*;
class PicClient
{
public static void main(String [] args)throws Exception
{
Socket s = new Socket("192.168.88.1",10003);
FileInputStream fis = new FileInputStream("c:\\1.bmp");
OutputStream out = s.getOutputStream();
byte [] buf = new byte[1024];
int len = 0 ;
while ((len = fis.read(buf))!=-1)
{
out.write(buf,0,len);
}
//告诉服务端数据已经写完。
s.shutdownOutput();
InputStream in = s.getInputStream();
byte[]bufIn = new byte[1024];
int num = in.read(bufIn);
System.out.println(new String(bufIn,0,num));
fis.close();
s.close();
}
}
class PicServer
{
public static void main(String []args)throws Exception
{
ServerSocket ss = new ServerSocket(10003);
Socket s = ss.accept();
InputStream in = s.getInputStream();
FileOutputStream fos = new FileOutputStream("D:\\server.bmp");
byte[]buf = new byte[1024];
int len = 0 ;
while((len = in.read(buf))!=-1)
{
fos.write(buf,0,len);
}
OutputStream out = s.getOutputStream();
out.write("上传成功!".getBytes());
fos.close();
s.close();
ss.close();
}
}
输出结果:
2、网络编程(TCP-客户端并发上传图片)
上一节的服务端有个局限性。当A客户连接上以后,被服务端获取到,服务端执行具体流程,这时B客户端连接,只有等待。因为服务端还没处理完A客户端的请求,还有循环回来执行下次accept方法。所以暂时获取不到B客户端对象。那么为了可以让多个客户端同时并发访问服务端,那么服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端的请求。
那么如何定义线程呢? 只要明确了每一个客户端要在服务端执行的代码即可。将该代码存入到run方法中。
Demo
import java.io.*;
import java.net.*;
class PicClient_1
{
public static void main(String [] args)throws Exception
{
if(args.length!=1)
{
System.out.println("请选择一个jpg格式的图片。");
return ;
}
File file = new File(args[0]);
if(!(file.exists()&&file.isFile()))
{
System.out.println("该文件有问题,要么不存在,要么不是文件");
return ;
}
if(!file.getName().endsWith(".jpg"))
{
System.out.println("图片格式错误,请重新选择");
return ;
}
if(file.length()>1024*1024*5)
{
System.out.println("文件过大,没安好心。");
return ;
}
Socket s = new Socket("192.168.88.1",10003);
FileInputStream fis = new FileInputStream(file);
OutputStream out = s.getOutputStream();
byte [] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf))!=-1)
{
out.write(buf,0,len);
}
//告诉服务端数据写完。
s.shutdownOutput();
InputStream in = s.getInputStream();
byte[]bufIn = new byte[1024];
int num = in.read(bufIn);
System.out.println(new String(bufIn,0,num));
fis.close();
s.close();
}
}
//定义线程
class PicThread implements Runnable
{
private Socket s ;
PicThread(Socket s )
{
this.s = s ;
}
public void run ()
{
int count = 1;
String ip = s.getInetAddress().getHostAddress();
try
{
System.out.println(ip+"....connected!");
InputStream in = s.getInputStream();
File file = new File("D:\\"+ip+"("+(count)+")"+".jpg");
while(file.exists())
{
file = new File("D:\\"+ip+"("+(count++)+")"+".jpg");
}
FileOutputStream fos = new FileOutputStream(file);
byte [] buf = new byte[1024];
int len = 0;
while((len= in.read(buf))!=-1)
{
fos.write(buf,0,len);
}
OutputStream out = s.getOutputStream();
out.write("上传成功".getBytes());
fos.close();
s.close();
}
catch (Exception e)
{
throw new RuntimeException(ip+"上传失败");
}
}
}
class PicServer_1
{
public static void main(String[]args)throws Exception
{
ServerSocket ss =new ServerSocket(10003);
while(true)
{
Socket s = ss.accept();
new Thread(new PicThread(s)).start();
}
}
}
输出结果:
3、网络编程(TCP-客户端并发登陆)
客户端通过键盘录入用户名,服务端对这个用户名进行校验。
如果该用户存在,在用户端显示xxx,已登录。并在客户端显示xxx,欢迎光临。
如果该用户存在,在服务器端显示xxx,尝试登陆,并在客户端显示xxx,该用户不存在
最多登陆3次。
测试代码:
import java.io.*;
import java.net.*;
class LoginClient
{
public static void main(String [] args)throws Exception
{
Socket s = new Socket("192.168.88.1",10003);
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
for(int x = 0;x<3;x++)
{
String line = bufr.readLine();
if(line == null)
{
break;
}
out.println(line);
String info = bufIn.readLine();
if(info.contains("欢迎"))
{
break;
}
}
bufr.close();
s.close();
}
}
class UserThread implements Runnable
{
private Socket s ;
UserThread(Socket s )
{
this.s = s;
}
public void run()
{
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"....connected");
try
{
for(int x = 0;x<3;x++)
{
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
String name = bufIn.readLine();
if(name ==null)
{
break;
}
BufferedReader bufr = new BufferedReader (new FileReader("D:\\user.txt"));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
String line = null;
boolean flag = false;
while((line = bufr.readLine())!=null)
{
if(line.equals(name))
{
flag =true;
break;
}
}
if(flag)
{
System.out.println(name+",已登录");
out.println(name+",欢迎光临");
break;
}
else
{
System.out.println(name+",尝试登陆");
out.println(name+",用户名不存在");
}
}
s.close();
}
catch (Exception e )
{
throw new RuntimeException("校验失败");
}
}
}
class LoginServer
{
public static void main(String [] args)throws Exception
{
ServerSocket ss = new ServerSocket(10003);
while(true)
{
Socket s = ss.accept();
new Thread(new UserThread(s)).start();
}
}
}
输出结果:
4、网络编程(浏览器客户端-自定义服务端)
演示客户端和服务端
(1)、客户端:浏览器IE:直接输入192.168.88.1:10003
(2)、服务端:自定义
测试代码:
import java.net.*;
import java.io.*;
class ServerDemo
{
public static void main(String[] args)throws Exception
{
ServerSocket ss = new ServerSocket(10003);
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress());
PrintWriter out =new PrintWriter(s.getOutputStream(),true);
out.println("客户端您好");
s.close();
ss.close();
}
}
输出结果:
5、网络编程(自定义浏览器-Tomcat服务器)
客户端:自定义浏览器 服务端:Tomcat服务器 首先,要模拟一个IE浏览器,就要了解浏览器是怎么样和服务器进行交互的,我们通过在IE浏览器上输入:http://localhost:10003去访问下面代码,就可以截取浏览器的访问信息,因此可以模拟IE与其他服务器交互的信息。
测试代码:
import java.io.*;
import java.net.*;
class ServerInfoRece
{
public static void main(String [] args)throws Exception
{
ServerSocket ss = new ServerSocket(10003);
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress());
InputStream in = s.getInputStream();
byte[]buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String (buf,0,len));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("客户端您好");
s.close();
ss.close();
}
}
输出结果:
由此可见:自定义服务器接收到了以下信息:
0:0:0:0:0:0:0:1
GET / HTTP/1.1
Host: localhost:10003
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/31.0.1650.63 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8
由此可以模仿以上模式编下一个浏览器去访问Tomcat服务器。
测试代码:
import java.io.*;
import java.net.*;
class MyIE
{
public static void main(String[]args)throws Exception
{
Socket s= new Socket("192.168.88.1",8080);
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("GET /myWeb/Hello.html HTTP/1.1");
out.println("Accept:*/*");
out.println("Accept-Language: zh-CN,zh;q=0.8");
out.println("Host:192.168.88.1:10003");
out.println("Connection:Closed");
out.println();//制造空格
out.println();//制造空格
BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
String line = null;
while((line = bufr.readLine())!=null)
{
System.out.println(line);
}
s.close();
}
}
以上代码的含义,该自定义IE欲访问的资源是服务器Tomcat上的资源,该服务器的端口是8080,然后给服务器发去浏览器的识别信息,即IE欲访问服务器,并请求获取在8080端口下myWeb文件夹下的Hello.html资源,因此在此路径要存在一个名为Hello.html的文件,里面内容如下,最后把内容打印在自定义IE的控制台上。
<!DOTTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>HTML 测试</TITLE>
</HEAD>
<BODY BGCOLOR="#FDF5E6">
<H1>HTML 测试</H1> 欢迎。
</BODY>
</HTML>
输出结果:
6、网络编程(自定义图形界面浏览器-Tomcat服务器)
Demo
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
class MyIEByGUI
{
private Frame f ;
private TextField tf ;
private Button but ;
private TextArea ta;
private Dialog d ;
private Label lab;
private Button okBut;
MyIEByGUI()
{
init();
}
public void init()
{
f = new Frame("my Internet Explorer");
f.setBounds(300,100,600,500);
f.setLayout(new FlowLayout());
tf = new TextField(60);
but = new Button("转到");
ta = new TextArea(25,70);
d = new Dialog(f,"提示信息-self",true);
d.setBounds(400,200,240,150);
d.setLayout(new FlowLayout());
lab = new Label();
okBut = new Button("确定");
d.add(lab);
d.add(okBut);
f.add(tf);
f.add(but);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
okBut.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
d.setVisible(false);
}
});
d.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
d.setVisible(false);
}
});
tf.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
try
{
if(e.getKeyCode() == KeyEvent.VK_ENTER)
{
showDir();
}
}
catch (Exception ex)
{
}
}
});
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
showDir();
}
catch (Exception ex)
{
}
}
});
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
private void showDir()throws Exception
{
ta.setText("");
String url = tf.getText();//http://192.168.88.1:8080/myWeb/Hello.html
int index1 = url.indexOf("//")+2;
int index2 = url.indexOf("/",index1);
String str = url.substring(index1,index2);//192.168.88.1:8080
String [] arr = str.split(":");
String host = arr[0];
int port = Integer.parseInt(arr[1]);
String path = url.substring(index2);
//ta.setText(str+"..."+path);
Socket s = new Socket(host,port);
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("GET /"+path+" HTTP/1.1");
out.println("Accept:*/*");
out.println("Accept-Language: zh-CN,zh;q=0.8");
out.println("Host:192.168.88.1:10003");
out.println("Connection:Closed");
out.println();//制造空格
out.println();//制造空格
BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while((line = bufr.readLine())!=null)
{
System.out.println(line);
ta.append(line+"\r\n");
}
ta.append("OVER");//结束标志
s.close();
}
public static void main(String[] args)throws Exception
{
new MyIEByGUI();
}
}
输出结果:
7、网络编程(URL类和URLConnection类)
java.net.URL URL类:类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。
String getFile();//获取此 URL 的文件名。
String getHost();//获取此 URL 的主机名(如果适用)。
String getPath();//获取此 URL 的路径部分。
String getPort();//获取此 URL 的端口号。
String getProtocol();//获取此 URL 的协议名称。
String getQuery();// 获取此 URL 的查询部分。
测试代码:
import java.net.*;
class URLDemo
{
public static void main(String[]args)throws MalformedURLException
{
URL url = new URL("http://192.168.88.1:8080/myWeb/Hello.html?name =haha&age=30");
System.out.println("getProtocol():"+url.getProtocol());
System.out.println("getHost():"+url.getHost());
System.out.println("getPort():"+url.getPort());
System.out.println("getPath():"+url.getPath());
System.out.println("getFile():"+url.getFile());
System.out.println("getQuery():"+url.getQuery());
}
}
输出结果:
令外一个很实用的类URLConnection,在于Java网络编程中非常实用,而且是在应用层上的使用,例如,下面的例子也同样提取8080端口服务器的html文件,可是提取出来的文件不带有传输层上文件的提示信息。
测试代码:
import java.net.*;
import java.io.*;
class URLConnectionDemo
{
public static void main(String [] args)throws Exception
{
URL url = new URL("http://192.168.88.1:8080/myWeb/Hello.html");
URLConnection conn = url.openConnection();
System.out.println(conn);
InputStream in = conn.getInputStream();
byte[]buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String (buf,0,len));
}
}
输出结果:
把前面图形化的IE例子里的showDir()代码改进后调试如下:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
class MyIEByGUI_NEW
{
private Frame f ;
private TextField tf ;
private Button but ;
private TextArea ta;
private Dialog d ;
private Label lab;
private Button okBut;
MyIEByGUI_NEW()
{
init();
}
public void init()
{
f = new Frame("my Internet Explorer");
f.setBounds(300,100,600,500);
f.setLayout(new FlowLayout());
tf = new TextField(60);
but = new Button("转到");
ta = new TextArea(25,70);
d = new Dialog(f,"提示信息-self",true);
d.setBounds(400,200,240,150);
d.setLayout(new FlowLayout());
lab = new Label();
okBut = new Button("确定");
d.add(lab);
d.add(okBut);
f.add(tf);
f.add(but);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
okBut.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
d.setVisible(false);
}
});
d.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
d.setVisible(false);
}
});
tf.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
try
{
if(e.getKeyCode() == KeyEvent.VK_ENTER)
{
showDir();
}
}
catch (Exception ex)
{
}
}
});
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
showDir();
}
catch (Exception ex)
{
}
}
});
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
private void showDir()throws Exception
{
ta.setText("");
String urlPath = tf.getText();//http://192.168.88.1:8080/myWeb/Hello.html
URL url = new URL(urlPath);
URLConnection conn = url.openConnection();
InputStream in = conn.getInputStream();
byte [] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
ta.setText(new String(buf,0,len));
}
public static void main(String[]args)throws Exception
{
new MyIEByGUI_NEW();
}
}
输出结果: