------------- android培训、 java培训、java博客、java学习型技术博客、期待与您交流! -------------网络编程 通过使用套接字来达到进程间通信目的的编程就是网络编程 通信的条件 1、找到对方IP 2、数据要发送到对方指定的应用程序上,为了标识这些应用型程序, 所以给这些网络应用都用数字进行标识,为了方便称呼这个数字,叫逻辑端口 3、定义通信规则,这个通信规则称为协议(按照同一种规则通讯) 通讯三要素 IP地址: 网络中设备的标识,本地回环地址:127.0.0.1 默认主机名:localhost 对应对象,InetAddress 端口号: 用于标识进程的逻辑地址,不同进程的标识 有效端口:0-65535,其中0-1024被系统程序所保留 就是一个数值,没有必要封装对象 传输协议 UDP:User Datagram Protocol;面向无连接 分发送端 和接收端 将数据及源和目的 封装成数据包中,不需要建立连接 每个数据包的大小限制在64k内 因为无连接,是不可靠协议 不需要建立连接,速度快 TCP:Transmission Control Protocol,面向连接 Socket和ServerSocket,客户端和服务端 建立连接,形成传输数据的通道 在连接中进行大数据量传输 通过三次握手完成连接,是可靠协议 必须建立连接,效率会稍低 Socket套接字 Socket就是为网络服务提供的一种机制 通信的两端都有Socket 网络通信其实就是Socket间的通信 数据在两个Socket间通过IO传输 IP地址 InetAddress 此类表示互联网协议IP地址 方法 static InetAddress getLocalHost() 返回本地主机 static InetAddress getByName(String host) 在给定主机名的情况下确定主机的IP地址 static InetAddress[] getAllByName(String host) ...返回ip地址数组 String getHostAddress() 返回ip地址字符串 String getHostName() 返回ip地址的主机名 UDP协议 public class DatagramSocket 此类表示用来发送和接受数据报包的套接字 public class DatagramPacket 此类表示数据报包 发送端 1、建立UDPsocket服务,通过DatagramSocket对象 2、提供数据,并将数据封装到数据包中 3、通过socket服务的send方法,将数据包发出去 4、关闭资源 接收端 1、定义udpsocket服务,通常会监听一个端口,其实就是给这个接受网络应用程序定义数字标识, 方便明确哪些数据过来是该应用程序处理的 2、定义一个数据包,因为要存储接收到的字节数据, 因为数据包对象中有更多功能可以提取字节数据中的不同数据信息 3、通过socket服务的receive方法将收到的数据存入已定义好的数据包中 4、通过数据包对象的特有功能,获取数据 5、关闭资源 TCP协议 public class Socket 此类实现客户端套接字 public class ServerSocket 此类实现服务器套接字 客户端 1、创建Socket服务,并指定要连接的主机和端口 2、获取Socket中的输出流向外发送数据 3、获取Socket中的输入流读取客户端反馈信息 4、关闭客户端 服务端 1、建立服务端的socket服务,ServerSocket();并监听一个端口, 2、获取连接过来的客户端对象 通过ServerSokcet的accept方法,没有连接就会等,这个方法是阻塞式的 3、客户端如果发过来数据,服务端要使用对应的客户端对象, 获取到该客户端对象的读取流来读取客户端发过来的数据 4、如需反馈服务端信息,则获取服务端写入流写入数据 5、关闭服务端(可选) 分类演示import java.net.*; class IPDemo { public static void main(String[] args)throws Exception { InetAddress i = InetAddress.getLocalHost(); //返回:主机名/字面值IP地址的字符串表示形式 System.out.println(i.toString()); System.out.println(i.getHostName()); System.out.println(i.getHostAddress()); //在给定主机名的情况下确定主机的IP地址 InetAddress ia = InetAddress.getByName("www.baidu.com"); InetAddress ia2 = InetAddress.getByName("119.75.217.56"); System.out.println("address:"+ia.getHostAddress()); System.out.println("name:"+ia.getHostName()); InetAddress[] iarr = InetAddress.getAllByName("www.baidu.com"); for(InetAddress inet : iarr) { System.out.println("baidu:"+inet.toString()); } } }
//UDP传输过程简单演示 import java.net.*; class UdpSend { public static void main(String[] args)throws Exception { //创建udp服务,通过DatagramSocket对象 DatagramSocket ds = new DatagramSocket(); //确定数据,并封装成数据包; DatagramPacket(byte[] buf,int length,InetAddress address , int port) byte[] buf= "udp ge men lai le".getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.108"),10000); //通过socket服务,将已有的数据包发送出去,通过send方法 ds.send(dp); //关闭资源 ds.close(); } } class UdpRece { public static void main(String[] args)throws Exception { //创建udp socket服务,建立端点 DatagramSocket ds = new DatagramSocket(10000);//建立监听10000端口 //定义数据包,用于存储数据 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf,buf.length); //通过服务的receive方法将收到数据存入数据包中 ds.receive(dp); //通过数据包的方法获取其中的数据 String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength()); int port = dp.getPort(); System.out.println(ip+":"+data+"::"+port); //关闭资源 ds.close(); } }
/* UDP传输,需求获取键盘录入,并定义结束语句, */ import java.net.*; import java.io.*; class UdpSend2 { public static void main(String[] args) throws Exception { DatagramSocket ds = new DatagramSocket(); BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; //readLine阻塞方法,等着键盘录入一行包括行终止符 while ((line=bufr.readLine())!=null) { if ("886".equals(line)) break; byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.108"),8888); //IP地址最后一段有两个不能用.0和.255,前者代表网络段,后者代表给1-254所有群发 ds.send(dp); } ds.close(); } } class UdpReceive2 { public static void main(String[] args)throws Exception { //此处不能放入循环中,否则会发生绑定异常,因为new多个服务,在一个端口上(上个服务端口还未在内存中释放) DatagramSocket ds = new DatagramSocket(8888); while(true) { byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf,buf.length); ds.receive(dp);//此方法为阻塞式方法,有就接受,没有就等待,不会死循环 String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength());//注意到这里写长度 System.out.println(ip+" : "+data); } } }
/* 编写一个聊天程序 有收数据的部分,和发数据的部分,这两部分需要同时执行, 因为收和发动作是不一致的,所以要定义两个run方法 并将这个两个方法封装到两个不同类中 两个run方法中内容就是上面演示示例内容 */ import java.io.*; import java.net.*; class Send implements Runnable { private DatagramSocket ds; Send(DatagramSocket ds) { this.ds = ds; } public void run() { try { BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while ((line=bufr.readLine())!=null) { if("886".equals(line)) break; byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.108"),10001); ds.send(dp); } } catch(Exception e) {} } } class Rece implements Runnable { private DatagramSocket ds; Rece(DatagramSocket ds) { this.ds=ds; } public void run() { try { while(true) { byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf,buf.length); ds.receive(dp); String id = dp.getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength()); System.out.println(id+" :: "+data); } } catch(Exception e) {} } } class Chat { public static void main(String[] args)throws Exception { DatagramSocket ds = new DatagramSocket(); DatagramSocket ds1 = new DatagramSocket(10001); new Thread(new Send(ds)).start(); new Thread(new Rece(ds1)).start(); } }
import java.io.*; import java.net.*; class TcpClient { public static void main(String[] args) throws Exception { //创建客户端的Socket服务,指定目的主机和端口 Socket s = new Socket("192.168.1.108",10003); //为了发送数据,应该获取socket流中的输出流 OutputStream out = s.getOutputStream(); out.write("tcp ge men lai le".getBytes()); s.close(); } } class TcpServer { public static void main(String[] args)throws Exception { //建立服务端socket服务,并监听一个端口, ServerSocket ss = new ServerSocket(10003); //通过accept方法获取连接过来的客户端对象 Socket s = ss.accept(); //阻塞方法 //若有客户端连接进来,就显示某某ip已连接上 String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"......connected"); //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); s.close(); } }
/* 演示tcp的传输的客户端和服务端的互访 需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息 */ import java.net.*; import java.io.*; class TcpClient2 { public static void main(String[] args)throws Exception { Socket s = new Socket("192.168.1.108",10004); InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); out.write("服务端,你好".getBytes()); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); s.close(); } } class TcpServer2 { public static void main(String[] args)throws Exception { ServerSocket ss = new ServerSocket(10004); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+".....connected"); 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(); } }
/* 需求:建立一个文本转换服务器,客户端给服务端发送文本,服务端会将文本转成大写在返回给客户端, 而且客户端可以不断的进行文本转换,当客户端输入over时,转换就会结束 */ import java.io.*; import java.net.*; class Client { public static void main(String[] args)throws Exception { Socket s = new Socket("192.168.1.108",10004); BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; while ((line=bufr.readLine())!=null) { if("over".equals(line)) break; out.println(line); System.out.println(in.readLine()); } bufr.close(); s.close(); } } class Server { public static void main(String[] args)throws Exception { ServerSocket ss = new ServerSocket(10004); Socket s =ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"is connected.."); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; while ((line=in.readLine())!=null) { out.println(ip+": "+line.toUpperCase()); } s.close(); ss.close(); } }
/* TCP,客户端传输数据到服务端,并接受服务端反馈信息 客户端定义输入流读取数据,然后使用Socket中输出流进行缓存, 服务端使用接受的Socket对象,获取其输入流读取数据,然后定义输出流将得到数据存储, 完毕后,使用客户端Scoket对象输出流写入反馈信息 客户端使用Socket对象中输入流读取反馈信息 */ import java.io.*; import java.net.*; class TextClient { public static void main(String[] args)throws Exception { Socket s = new Socket("192.168.1.108",10006); BufferedReader bufr = new BufferedReader(new FileReader("IPDemo.java")); PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; while ((line=bufr.readLine())!=null) { out.println(line); } s.shutdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记-1 BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); String str = in.readLine(); //若无关闭,此处在读,等待 System.out.println(str); s.close(); bufr.close(); } } class TextServer { public static void main(String[] args)throws Exception { ServerSocket ss = new ServerSocket(10006); Socket s = ss.accept(); String id = s.getInetAddress().getHostAddress(); System.out.println(id+".....is connected"); PrintWriter pw = new PrintWriter(new FileOutputStream("copy_IPDemo.txt"),true); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); String line = null; while ((line=in.readLine())!=null) //等待,所以要结束 { pw.println(line); } PrintWriter out = new PrintWriter(s.getOutputStream(),true); out.println("上传成功"); s.close(); ss.close(); pw.close(); } }
/* 上述示例服务端都有个局限性,当一个客户端连接上以后,被服务端获取,服务端执行具体流程 这时其他客户端连接,只有等待 因为服务端还没有处理完A客户端的请求,还未结束本次循环回路执行下次accpet方法 所以暂时获取不到B客户端对象 那么为了可以让多个客户端同时并发访问服务端 那么服务端最好就是将每个客户端封装到一个单独的线程中,这样就可以同时处理多个客户 演示: 并发上传+判断条件,+覆盖文件处理 */ import java.io.*; import java.net.*; class PicClient { public static void main(String[] args)throws Exception { File file = new File(args[0]); //给传输的文件进行条件设置 if (args.length!=1) { System.out.println("only one JPG file"); return; } if (!(file.exists()&&file.isFile())) { System.out.println("file is not exists or error"); return; } if (!file.getName().endsWith(".jpg")) { System.out.println("wrong format,please choose jpg format"); return; } if(file.length()>1024*1024*10) { System.out.println("File is too big to load"); return; } method(file); } public static void method(File file)throws Exception { Socket s = new Socket("192.168.1.108",10006); 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[] buf2 = new byte[1024]; int num = in.read(buf); System.out.println(new String(buf,0,num)); fis.close(); s.close(); } } class PicThread { public static void main(String[] args)throws Exception { ServerSocket ss = new ServerSocket(10006); while (true) { Socket s = ss.accept(); new Thread(new PicServer(s)).start(); } } } class PicServer implements Runnable { private Socket s; PicServer(Socket s) { this.s = s; } public void run() { int count =1; String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...is connected"); try { //用ip地址进行文件区分,若文件名一样则复制但不替换,文件名改为文件名(n) File file = new File(ip+"("+count+")"+".jpg"); while(file.exists()) file = new File(ip+"("+(count++)+")"+".jpg"); FileOutputStream fos = new FileOutputStream(file); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = 0; while ((len=in.read(buf))!=-1) { fos.write(buf,0,len); } fos.close(); OutputStream out = s.getOutputStream(); out.write("succeded to upload".getBytes()); } catch (Exception e) { throw new RuntimeException("faied to load"); } } }
------------- android培训、 java培训、java博客、java学习型技术博客、期待与您交流! -------------详情请查看:http://edu.csdn.net/heima/
黑马程序员_网络编程
最新推荐文章于 2022-10-30 22:12:01 发布