黑马程序员-网络编程
2015-10-15 11:58
465 查看
——- android培训、java培训、期待与您交流! ———-
2)TCP面向连接,可传输大树据,经过三次握手协议,可靠,但是速度慢,消耗资源。TCP相当于打电话,UDP相当于邮局寄信。下载用的是TCP。
1)创建socket对象
2)确定数据,并把数据打包
3)发送数据
4)关闭资源socket
UDP接受数据步骤
1)创建socket对象,并指定接受端口号
2)定义空的数据报,准备存储接受到的数据,并利用数据报中的方法解析数据的各种信息。
3)接收数据
4)解析数据
5)关闭资源
192.168.1.255是个广播地址。可以给所有机器发广播。
示例1: 从键盘接收数据,可以一对一发,也可以群发。
示例2:聊天工具,用两个线程来写,同样是从键盘录入数据。
注2:需要建立连接才能执行,需要先运行服务器,在运行客户端
客户端建立步骤
1. 创建socket对象,并设置连接地址和端口号
2. 获得输出流
3. 加载数据到输出流中
4. 关闭客户端
服务器建立步骤
1. 创建server对象,设置自己的监听端口号
2. 获得客户端socket对象
3. 获得客户端对象的输入流,并读取数据
4. 关闭客户端。
示例3:客户端发送数据,服务器端接收数据,并反馈给客户端,客户端接收反馈并打印。
示例4:客户端通过键盘录入文本数据,服务器将文本转换成大写返回给客户端。
1)用字符缓冲流完成
2)改错。客户端和服务器都在莫名的等待,原因是里面出现了阻塞式方法,这些方法没有读到结束标记,所以一直处于等待状态。
示例5:上传文本数据。从客户传送硬盘文件到服务器端硬盘。文本文件。
出现问题:
1)没有结束标记位
2)socket内部定义的结束关闭流标志位的方法。shutdownOutput();
示例6:上传图片。(练习)
一个传一个收。
一个服务器,同时可以处理多个客户端的请求。用多线程处理。
注意:需要开启新的线程,需要保存路径是原有文件不被覆盖,需要传输特定格式和特定大小的文件。
我们把http协议,IP地址,端口号和请求内容封装到一个类中,称为URL。
通过URL,我们可以:
(1)获得协议名称,IP地址,端口号,请求内容等;
(2)可以直接获得客户端和服务器端的连接通道。
需要注意一点:getPort()方法,如果没有输入端口号,则默认为-1;需要如下判断:
以上是网络编程的基本概念和基本思想,多做练习,多理解,多复习。
网络编程
UDP和TCP协议各自优缺点
1)UDP面向无连接,数据报大小有限制64K之内封包,不可靠,容易丢包,但是速度快!因此针对于数据不重要,追求速度快的常用此类协议,如聊天工具/网络视频会议。2)TCP面向连接,可传输大树据,经过三次握手协议,可靠,但是速度慢,消耗资源。TCP相当于打电话,UDP相当于邮局寄信。下载用的是TCP。
(一)UDP协议
UDP发送数据步骤四步1)创建socket对象
2)确定数据,并把数据打包
3)发送数据
4)关闭资源socket
[code]public class UDPSend { public static void main(String args[]) { DatagramSocket ds = new DatagramSocket(8888); byte[] buf = "hello world!".getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,"192.163.1.34","10000"); ds.send(dp); ds.close(); } }
UDP接受数据步骤
1)创建socket对象,并指定接受端口号
2)定义空的数据报,准备存储接受到的数据,并利用数据报中的方法解析数据的各种信息。
3)接收数据
4)解析数据
5)关闭资源
[code]public class UDPRece { public static void main(String args[]) { DatagramSocket ds = new DatagramSocket(8888); byte[] buf = new byte[1024];//最大为6k DatagramPacket dp = new DatagramPacket(buf,buf.length); ds.receive(dp); String address = dp.getAdrress().getHostAdrress(); String data = new String(dp.getData(),0,dp.getLength()); int port = dp.getPort(); System.out.println(address+"..."+data+"..."+port); ds.close(); } }
192.168.1.255是个广播地址。可以给所有机器发广播。
示例1: 从键盘接收数据,可以一对一发,也可以群发。
[code]public class UDPSend { public static void main(String args[]) { DatagramSocket ds = new DatagramSocket(8888); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = null; while((line=br.readLine())!=null) { if(line.equals("bye")) break; byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.163.1.34"),"10000"); ds.send(dp); } ds.close(); } }
[code]public class UDPRece { public static void main(String args[]) { DatagramSocket ds = new DatagramSocket(8888); while(true) { byte[] buf = new byte[1024];//最大为6k DatagramPacket dp = new DatagramPacket(buf,buf.length); ds.receive(dp); String address = dp.getAdrress().getHostAdrress(); String data = new String(dp.getData(),0,dp.getLength()); int port = dp.getPort(); System.out.println(address+"..."+data+"..."+port); } } }
示例2:聊天工具,用两个线程来写,同样是从键盘录入数据。
[code]class UDPSend implements Runnable { private DatagramSocket ds; public UDPSend(DatagramSocket ds) { this.ds = ds; } public void run() { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = null; while((line=br.readLine())!=null) { if(line.equals("bye")) break; byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.163.1.34"),"10000"); ds.send(dp); } ds.close(); } }
[code]class UDPRece implements Runnable { private DatagramSocket ds; public UDPRece(DatagramSocket ds) { this.ds = ds; } public void run() { while(true) { byte[] buf = new byte[1024];//最大为6k DatagramPacket dp = new DatagramPacket(buf,buf.length); ds.receive(dp); String address = dp.getAdrress().getHostAdrress(); String data = new String(dp.getData(),0,dp.getLength()); int port = dp.getPort(); System.out.println(address+"..."+data+"..."+port); } } }
[code]public class TestDemo { public static void main(String args[]) { DatagramSocket ds1 = new DatagramSocket(); DatagramSocket ds2 = new DatagramSocket(10000); new Thread(new UDPSend(ds1)); new Thread(new UDPRece(ds2)); } }
(二)TCP协议
注1:客户端和服务器注2:需要建立连接才能执行,需要先运行服务器,在运行客户端
客户端建立步骤
1. 创建socket对象,并设置连接地址和端口号
2. 获得输出流
3. 加载数据到输出流中
4. 关闭客户端
[code]class TCPClient { public static void main(String args[]) { Socket sc = new Socket("192.168.1.254",10003); OutputStream out = ss.getOutputStream(); out.write("hello world".getBytes()); sc.close(); } }
服务器建立步骤
1. 创建server对象,设置自己的监听端口号
2. 获得客户端socket对象
3. 获得客户端对象的输入流,并读取数据
4. 关闭客户端。
[code]class TCPServer { public static void main(String args[]) { ServerSocket ss = new ServerSocket(10003); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"......."); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); s.close(); } }
示例3:客户端发送数据,服务器端接收数据,并反馈给客户端,客户端接收反馈并打印。
[code]class TCPClient { public static void main(String args[]) { Socket s = new Socket("192.168.1.254",10001); OutputStream out = s.getOutputStream(); out.write("你好,服务器!".getBytes()); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = 0; while((len=in.read(buf))!=-1) { System.out.println(new String(buf,0,len)); } s.close(); } }
[code]class TCPServer { public static void main(String args[]) { ServerSocket ss = new ServerSocket(10001); Socket s = ss.accept(); String ip = 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)); OutputStream out = s.getOutputStream(); out.write("客户端,谢谢,已收到!!".getBytes()); s.close(); ss.close(); } }
示例4:客户端通过键盘录入文本数据,服务器将文本转换成大写返回给客户端。
1)用字符缓冲流完成
2)改错。客户端和服务器都在莫名的等待,原因是里面出现了阻塞式方法,这些方法没有读到结束标记,所以一直处于等待状态。
[code]class TCPClient { public static void main(String args[]) { Socket s = new Socket("192.168.1.254",10002); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufbw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); BufferedReader bufbr = new BufferedReader(new InputStreamReader(s.getInputStream())); String line = null; while((line=in.readLine())!=null) { if(line.equals("over")) break; bufbw.write(line); bufbw.newLine(); bufbw.flush(); String str = bufr.readLine(); System.out.println("server:"+str); } } }
[code]class TCPServer { public static void main(String args[]) { ServerSocket ss = new ServerSocket(10003); Socket s = ss.accept(); BufferedReader bufbr = new BufferedReader(new InputStreamReader(s.getInputStream())); BufferedWriter bufbw = new BufferedReader(new OutputStreamWriter(s.getOutputStream())); String line = null; while((line = bufbr.readLine())!=null) { bufbw.write(line.toUpperCase()); bufbw.newLine(); bufbw.flush(); } s.close(); ss.close(); } }
示例5:上传文本数据。从客户传送硬盘文件到服务器端硬盘。文本文件。
出现问题:
1)没有结束标记位
2)socket内部定义的结束关闭流标志位的方法。shutdownOutput();
[code]class TCPClient { public static void main(String args[]) { Socket s = new Socket("192.168.1.254",10002); BufferedReader in = new BufferedReader(new FileReader("c:\\client.txt")); PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()),true); bufbr = new BufferedReader(new InputStreamReader(s.getInputStream())); String line = null; while((line=in.readLine())!=null) { pw.println(line); } s.shutdownOutput(); String str = bufr.readLine(); System.out.println("server:"+str); in.close(); s.close(); } }
[code]class TCPServer { public static void main(String args[]) { ServerSocket ss = new ServerSocket(10003); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); BufferedReader bufbr = new BufferedReader(new InputStreamReader(s.getInputStream())); BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\server.txt"),true); String line = null; while((line = bufbr.readLine())!=null) { bw.write(line); } PrintWriter bufbw = new PrintWriter(new OutputStreamWriter(s.getOutputStream())); bufbw.write("上传成功!!!!") s.close(); ss.close(); } }
示例6:上传图片。(练习)
一个传一个收。
[code]class TCPClient { public static void main(String args[]) { Socket s = new Socket("192.168.1.254",10002); InputStream in = new FileInputStream("c:\\1.png"); OutputStream out = s.getOutputStream(); byte[] buf = new byte[1024]; int len = 0 ; while((len=in.read(buf))!=-1) { out.write(buf); } s.shutdownOutput(); InputStream is = s.getInputStream(); byte[] buf1 = new byte[1024]; int len1 = is.read(buf1); System.out.println(new String(buf1,0,len1)); in.close(); s.close(); } }
[code]class TCPServer { public static void main(String args[]) { ServerSocket ss = new ServerSocket(10003); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); InputStream in = s.getInputStream(); OutputStream ou = new FileOutputStream("d:\\2.png"); byte[] buf = new byte[1024]; int len = 0; while((len=in.read(buf))!=-1) ou.write(buf,0,len); OutputStream out = s.getOutputStream(); out.write("上传成功!!".getBytes()); ou.close(); s.close(); ss.close(); } }
一个服务器,同时可以处理多个客户端的请求。用多线程处理。
注意:需要开启新的线程,需要保存路径是原有文件不被覆盖,需要传输特定格式和特定大小的文件。
[code]class uploadThread { private Socket socket; public uploadThread(Socket socket) { this.socket = socket; } public void run() { try { int count = 1; String ip = s.getInetAddress().getHostAddress(); InputStream in = s.getInputStream(); File file = new File(ip+"("+count+")"+".png"); while(file.exist()) { File file = new File(ip+"("+(count++)+")"+".png"); } OutputStream ou = new FileOutputStream(file); byte[] buf = new byte[1024]; int len = 0; while((len=in.read(buf))!=-1) ou.write(buf,0,len); OutputStream out = s.getOutputStream(); out.write("上传成功!!".getBytes()); ou.close(); s.close(); }catch(Exception e) { throw new RuntimeException(ip+"上传失败!!") } } }
[code]class TCPServer { public static void main(String args[]) { ServerSocket ss = new ServerSocket(10003); while(true) { Socket s = ss.accept(); new Thread(new uploadThread(s)).start(); } } }
[code]class TCPClient { public static void main(String args[]) { if(args.length!=1) { System.out.println("请选择一个图片格式的文件上传"); return; } File file = args[0]; if(!(file.exist()&&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",10002); InputStream in = new FileInputStream(file); OutputStream out = s.getOutputStream(); byte[] buf = new byte[1024]; int len = 0 ; while((len=in.read(buf))!=-1) { out.write(buf); } s.shutdownOutput(); InputStream is = s.getInputStream(); byte[] buf1 = new byte[1024]; int len1 = is.read(buf1); System.out.println(new String(buf1,0,len1)); in.close(); s.close(); } }
(三) URL
我们所常用的浏览器,实际上就是一个客户端,输入内容为http://IP:端口号?key=alue,就相当于发送请求。我们把http协议,IP地址,端口号和请求内容封装到一个类中,称为URL。
通过URL,我们可以:
(1)获得协议名称,IP地址,端口号,请求内容等;
(2)可以直接获得客户端和服务器端的连接通道。
[code]public class URLDemo { public static void main(String args[]) throws Exception { URL url = new URL("http://192.168.1.245:8080/myweb/demo.html?name=hahha&age=39"); System.out.println("getProtocol()"+url.getProtocol());//获得协议 System.out.println("getHost()"+url.getHost());//获得IP地址 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 con = url.getConnection();//返回数据没有头信息。//这属于应用层。 InputStream in = url.openStream();//直接开流 } }
需要注意一点:getPort()方法,如果没有输入端口号,则默认为-1;需要如下判断:
[code]int port = url.getPort(); if(port==-1) port = 80;
以上是网络编程的基本概念和基本思想,多做练习,多理解,多复习。
相关文章推荐
- NFS 网络文件系统制作
- TCP/IP协议三次握手与四次握手流程解析
- Http协议详解
- Android post请求网络数据(json作为参数)
- XML和解析
- TCP三次握手详解及释放连接过程
- 从keep-alive原理分析TCP游戏服务端心跳包的实用功能
- Linux 笔记 检查状态/监控网络流量
- Nginx SSL+tomcat集群,request.getScheme() 取到https正确的协议
- OpenStack(Kilo版本)网络服务neutron的安装部署
- 超全超详细的HTTP状态码大全
- HTTP/1.0和HTTP/1.1支持的方法
- 神经网络和BP算法推导
- 用户IP地址的三个属性的区别(HTTP_X_FORWARDED_FOR,HTTP_VIA,REM_addr
- iOS9 HTTP 不能正常使用的解决办法
- HTTP在abap中的应用
- SIP SDP RTSP RTP RTCP webrtc
- tcpdump抓真机包
- 【iOS】网络操作与AFNetworking
- iOS开发中的网络请求