需求:上传图片。
客户端。
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.1.254",10007); 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(10007); Socket s = ss.accept(); //拿到Socket对象 InputStream in = s.getInputStream(); //读取Socket流中的数据 FileOutputStream fos = new FileOutputStream("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(); } }
需求:上传图片。
客户端。
1,服务端点。
2,读取客户端已有的图片数据。
3,通过socket 输出流将数据发给服务端。
4,读取服务端反馈信息。
5,关闭。
import java.io.*; import java.net.*; class PicClient { public static void main(String[] args)throws Exception { //通过主函数传值的形式 if(args.length!=1) // =1就是往里边传了一个参数 !=1就是传入出错 { System.out.println("请选择一个jpg格式的图片"); return ; } File file = new File(args[0]); //传路径进来 把路径封装成file对象 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.1.254",10007); // 建立连接 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(); } }
服务端
这个服务端有个局限性,当A客户端连接上以后,被服务端获取.服务端执行具体流程
这时B客户端连接,只有等待.
因为服务端还没有处理完A客户端的请求.还没有循环回来,执行下一次accept方法,
所以暂时获取不到B客户端对象.
那么为了可以让多个客户端同时并发访问服务端.
那么服务端最好就是将每个客户端封装到一个单独的线程中.这样就可以同时处理多个客户端请求.
如何定义线程呢?
只要明确了每一个客户端要在服务端执行的代码即可.将改代码存入run方法中
定义线程,很重要
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(); //为了不让后添加的图片不覆盖前面的图片 就拿ip地址来命名 File dir = new File("d:\\pic"); File file = new File(dir,ip+"("+(count)+")"+".jpg");//192.168.1.254(1).jpg while(file.exists()) //判断上面的文件名是否存在 若存在 就往下执行 再new一个 file = new File(dir,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 { public static void main(String[] args) throws Exception //主函数一执行 会有一个主线程 { ServerSocket ss = new ServerSocket(10007); //紧跟着建立服务 while(true) // 循环建立线程 { Socket s = ss.accept(); //while 进来后就开始等待 主线程在等待 // 若真进来一个a客户端进来的话就往下执行, new Thread(new PicThread(s)).start(); // a客户端被Thread对象封装进去了 单独开了一个线程 /*这个时候有俩线程 一个主线程 一个a客户端所在线程 两个线程可以同时执行 a客户端开始跑起来,主线程还能执行,while 进来后就开始等待 主线程在等待 这个时候b就连进来了,获取到后accept(); 就new一个b的线程 这个时候a还在跑,b也可以跟着跑起来。 服务器得弄成多线程,*/ } //ss.close(); } }
要将客户端封装在线程当中 服务端开启多个线程来处理 客户端的并发请求访问
package demo3; /** * TCP客户端并发登陆 */ /*客户端通过键盘录入用户名. * 服务端对这个用户名进行校检. * * 如果用户存在,在服务端显示XXX,已登录. * 并在客户端显示XXX,欢迎光临 * * 如果用户不存在,在服务端显示XXX,尝试登陆. * 并在客户端显示XXX,用户已登录. * * * */ import java.io.*; import java.net.*; //客户端 class LoginChlient { public static void main(String[] args)throws Exception { Socket s = new Socket("192.168.1.100",10008); //键盘录入 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++)//限定3次 { String line = bufr.readLine(); //判断,如果输入的信息为空,那么就跳出去 if(line == null) { break; } out.println(line); String info = bufIn.readLine(); System.out.println("info:"+info); //如果返回的信息包含欢迎,那么就跳出去 if(info.contains("欢迎")) { break; } } //关掉键盘录入,关掉连接 bufr.close(); s.close(); } } //客户端 class LoginServer { public static void main(String[] args)throws Exception { @SuppressWarnings("resource") ServerSocket ss = new ServerSocket(10008); while(true) { Socket s = ss.accept(); new Thread(new UserThread(s)).start(); } } } //线程 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; } //校验用户名的文件 @SuppressWarnings("resource") BufferedReader bufr = new BufferedReader(new FileReader("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赋值为真. { flag = true; break; } } if(flag) { System.out.println(name+",已登录"); out.println(name+",欢迎光临"); break;//这里调用的是3次循环跳出 } else { System.out.println(name+"尝试登陆"); out.println(name+"用户不存在"); } } s.close(); } catch(Exception e) { throw new RuntimeException("连接失败"); } } }
/* * 演示客户端和服务端 * 1, * 客户端:浏览器 * 服务端:自定义 */ import java.io.*; import java.net.*; /*建立服务端 * */ class ServerDemo { public static void main(String[] args)throws Exception { ServerSocket ss = new ServerSocket(11000); Socket s = ss.accept(); //打印ip System.out.println(s.getInetAddress().getHostAddress()); PrintWriter out = new PrintWriter(s.getOutputStream(),true); out.println("<font color='red' size = 8>客户端你好</font>"); s.close(); ss.close(); } } //在浏览器当中输入 //http://192.168.1.100:11000/
//也可这样,在dos中输入,这个是远程登录的工具,可以进行命令方式的配置 //telnet 192.168.1.254 11000
在Tomcat目录的webapps目录下创建一个myweb目录
创建一个demo.html
在demo.html里面创建
<html>
<body>
<h1>这是我的主页</h1>
<font size=5 color=red>欢迎光临</font>
<div>
想做一首诗0.0</br>
想做一首诗0.0</br>
想做一首诗0.0</br>
</div>
</body>
</html>
打开tomcat目录下bin目录下的startup.bat
然后在浏览器中输入http://127.0.0.1:8080/myweb/demo.html
输入http://127.0.0.1:11000/myweb/demo.html
浏览器给服务端发送的消息:
127.0.0.1
GET /myweb/demo.html HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; BIDUBrowser 2.x)
Accept-Encoding: gzip, deflate
Host: 127.0.0.1:11000
Connection: Keep-Alive
请求消息体....(请求消息体上面肯定有一行空行)
以上是Http请求的消息头
GET是 获取请求的目标路径/目标文件 协议
Accept:浏览器支持的格式
Accept-language:建立中文版(语言)
Accept-Encoding:支持压缩格式
User-Agent:用户的一些信息
Host:IP地址以及端口
Connection:连接(Keep-Alive,保持存活)
以下是Http应答消息头
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"193-1367051592334"
Last-Modified: Sat, 27 Apr 2013 08:33:12 GMT
Content-Type: text/html
Content-Length: 193
Date: Sat, 27 Apr 2013 09:11:08 GMT
Connection: close
消息体......
----
HTTP/1.1 200 OK其中200代表的是响应状态码,并且成功
Last-Modified:修改时间
Content-Type:文本格式
Content-Length:大小是193字节
Date:事件
Connection:连接关闭
import java.io.*; import java.net.*; class MyIE { public static void main(String[] args)throws Exception { Socket s = new Socket("192.168.1.254",8080);//因为不是图形化界面就写死 PrintWriter out = new PrintWriter(s.getOutputStream(),true); // 给服务器发数据 out.println("GET /myweb/demo.html HTTP/1.1"); out.println("Accept: */*"); out.println("Accept-Language: zh-cn"); out.println("Host: 192.168.1.254:11000"); 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); } s.close(); } }
/*图形化界面的IE * */ 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 window"); 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://127.0.0.1:8080/myweb/demo.html int index1 = url.indexOf("//")+2; int index2 = url.indexOf("/",index1); String str = url.substring(index1,index2); 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"); out.println("Host: 192.168.1.254:11000"); out.println("Connection: closed"); out.println(); out.println(); BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream())); String line = null; while((line=bufr.readLine())!=null) { ta.append(line+"\r\n"); } s.close(); } public static void main(String[] args) { new MyIEByGUI(); } }
java.net.URL
统一资源定位符
String getFile()
获取此 URL 的文件名。
String getHost()
获取此 URL 的主机名(如果适用)。
String getPath()
获取此 URL 的路径部分。
int 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.1.254/myweb/demo.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()); /*int port = getPort(); if(port==-1) port = 80; getPort()==-1 } }
先说一下Socket()比较特殊的部分
在进行Socket()建立的时候有一个空参数的构造函数
会有一个connect(SocketAddress endpoint)方法进行连接
SocketAddress//网络地址,与InetAddress的区别在于InetAddress封装的是地址
//SocketAddress是抽象类,说一下他的子类InetSocketAddress封装的是地址+端口号
再说一下ServerSocket()比较特殊的部分
ServerSocket(int port,int backlog);//(int 端口,int 队列最大长度)代表的是能连接到服务器最大客户端服务个数,一般是50,可以设置
http://127.0.0.1:8080/myweb/demo.html
www.sina.com.cn//想要将主机名翻译成ip地址需要域名解析,需要一个dns域名解析服务器
0,在找之前先去找本地c:windows\systems\drivers\ext\host有没有映射
1,客户端首先去找一台DNS域名解析服务器,服务器记录的是sina的主机对应的ip地址(202.108.33.60)的记录表
2,DNS将域名地址(202.108.33.60)返回给客户端
3,客户端再次向ip(202.108.33.60)的8080端口上
http://127.0.0.1:8080
http://localhost:8080
其实127和localhost的映射关系就在本机上
c:windows\systems\drivers\ext\host
有个小应用,
可以把那种已经在本地准注册的软件,将去网络注册的网络ip映射写入到
c:windows\systems\drivers\ext\host当中,这样子可以走你指定的地址.(*^__^*) ……
结果你懂的..
第二个应用,
可以把一些垃圾网站,有木马的网站都映射到这个地方.屏蔽网站
但是如果直接写ip的话,就走ip不走网络映射