DNS 域名解析服务器,存储了IP与域名的对应关系
Socket是为网络服务提供的一种机制。通信两端都有Socket.网络通信就是Socket之间的通信,数据在两Socket间通过IO传输
UDP 对应Socket对象 DatagramSocket
发送端
创建UDP的Socket服务,(是否指定端口号均可) DatagramSocket ds = new DatagramSocket([端口号,可有可无]);将要发送到数据封装到数据包中 byte[] buf = "UDP传输演示,发送端数据".getBytes(); DatagramPacket dp = new DatagramPacket(byte[],byte[].length, InetAddress.getLocalHost(), 9999);通过UDP的Socket服务的send()方法将数据包发送 ds.send(dp);关闭Socket服务 ds.close();接收端
建立Socket服务,因是接收数据,必须要绑定端口与发送方数据包指定的端口号相同 DatagramSocket ds = new DatagramSocket(9999);创建数据包,用于存储收到数据。方便用数据包的方法解析这些数据 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length);通过UDP的Socket服务的receive方法将接收到的数据存储到数据包中 ds.receive(dp);阻塞式通过数据包对象的方法解析数据包的数据 dp.getAddress().getHostAddress()获取发送方IP地址 dp.getAddress().getHostName())获取发送方主机名 new String(dp.getData(),0,dp.getLength())获取发送方数据 dp.getPort()获取发送方端口号关闭Socket服务 ds.close();例 UDP发送端
public static void main(String[] args) throws IOException { //1.创建UDP的Socket服务 DatagramSocket ds = new DatagramSocket(); //2.将要发送到数据封装到数据包中 byte[] buf = "UDP传输演示,发送端数据".getBytes(); DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 9999); //3.通过UDP的Socket服务的send()方法将数据包发送 ds.send(dp); //4.关闭Socket服务 ds.close(); }UDP接收端
public static void main(String[] args) throws IOException { //1.建立Socket服务,因是接收数据,要绑定端口 DatagramSocket ds = new DatagramSocket(9999); //2.创建数据包,用于存储收到数据。方便用数据包的方法解析这些数据 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length); //3.通过UDP的Socket服务的receive方法将接收到的数据存储到数据包中 ds.receive(dp);//阻塞式 //4.通过数据包对象的方法解析数据包的数据 System.out.println(dp.getAddress().getHostAddress()); System.out.println(dp.getAddress().getHostName()); System.out.println(new String(dp.getData(),0,dp.getLength())); System.out.println(dp.getPort()); //5.关闭Socket服务 ds.close(); }TCP 对应Socket对象 两个: 客户端Socket 服务端ServerSocket
发送端
创建TCP客户端socket服务。使用的是Socket对象 Socket socket = new Socket(InetAddress.getLocalHost(), 9090);Socket socket = new Socket("192.168.1.111", 9090);Socket socket = new Socket(); SocketAddress address = new InetSocketAddress("ip/主机名", 9090); socket.connect(address) 如果连接建立成功,说明数据传输通道建立 该通道是socket流,是底层建立的,既有输入又有输出。从Socket获取输入/输出流流对象 通过getOutputStream()和getInputStream()来获取两个字节流 获取Socket输出流对象, 通过该流把数据发送给服务器 OutputStream out = ocket.getOutputStream();使用输出流,将数据写出。 out.write(String.getBytes());关闭资源,断开连接 socket.close();服务端
创建Socket服务,通过ServerScoket对象。服务器必须对外提供一个端口,否则客户端无法连接。 ServerSocket serverSocket = new ServerSocket(9090);获取连接过来的客户端对象。 Socket socket = serverSocket.accept();通过客户端对象获取Scoket流读取客户端发来的数据。 InputStream in = socket.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); String str = new String(buf,0,len);关闭资源。关客户端,关服务端。 serverSocket.close(); socket.close();例 TCP客户端
public static void main(String[] args) throws IOException { // 建立TCP客户端与服务器的连接, 指定服务器的IP地址与程序对应的端口号 Socket socket = new Socket(InetAddress.getLocalHost(), 9090); //InetAddress address = InetAddress.getByName(IP/主机名) ; //Socket socket = new Socket(address, 9090); // 获取Socket输出流对象, 通过该流把数据发送给服务器 OutputStreamWriter socketOut = new OutputStreamWriter(socket.getOutputStream()); //BufferedWriter bw = new BufferedWriter(socketOut); // 获取Socket输入流对象, 通过该流获得服务器发送给客户端的数据 BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 获取键盘输入流对象,读取数据 BufferedReader keyboardReader = new BufferedReader(new InputStreamReader(System.in)); String line = null; System.out.print("我说:"); while ((line = keyboardReader.readLine()) != null) { socketOut.write(line + "\n");//阻塞方法,加入"\n"结束标记,告诉服务器我发送完毕,使用BufferedWriter,可以用bw.newLine()代替 bw.write(line); // 刷新,见BufferWriter socketOut.flush(); // 读取服务器端返回的数据 line = socketReader.readLine(); System.out.println("服务器:" + line); System.out.print("我说:"); } socket.close(); }TCP服务端
public static void main(String[] args) throws IOException { // 创建服务器端, 注册当前程序的端口号 ServerSocket serverSocket = new ServerSocket(9090); // 接受客户端的连接,产⽣生⼀一个Socket Socket socket = serverSocket.accept(); // 获取Socket的输⼊入流, 就是通过这个输入流获得客户端发送给服务器的数据 BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 获取Socket的输出流, 就是通过该输出流, 服务器把数据发送给客户端 OutputStreamWriter socketOut = new OutputStreamWriter(socket.getOutputStream()); //BufferedWriter bw = new BufferedWriter(socketOut); // 获取键盘的输⼊入流,通过该输入流读取键盘上输入的数据 BufferedReader keyboardReader = new BufferedReader(new InputStreamReader(System.in)); // 不断读取客户端数据 String line = null; while ((line = socketReader.readLine()) != null) { System.out.println("客户端:" + line); System.out.print("我说:"); line = keyboardReader.readLine(); socketOut.write(line + "\n");//阻塞方法,加入"\n"结束标记,告诉客户端我发送完毕,使用BufferedWriter,可以用bw.newLine()代替 bw.write(line); socketOut.flush();//见BufferWriter } // 关闭 serverSocket.close(); }TCP多线程—多用户上传
客户端
public class TransClient { public static void main(String[] args) throws IOException { // 建立TCP客户端与服务器的连接, 指定服务器的IP地址与程序对应的端口号 Socket socket = new Socket(InetAddress.getLocalHost(), 9090); //InetAddress address = InetAddress.getByName(IP/主机名) ; //Socket socket = new Socket(address, 9090); // 获取Socket输出流对象, 通过该流把数据发送给服务器 OutputStream outputStream = socket.getOutputStream(); InputStream is = new FileInputStream("D:/1.mp4"); byte[] bytes = new byte[256]; int len = is.read(bytes);//返回读取到的有效字节数 while(len != -1) { outputStream.write(bytes,0,len); len = is.read(bytes); } socket.close(); } }服务端
public class TransServer { public static void main(String[] args) throws IOException{ // 创建服务器端, 注册当前程序的端口号 ServerSocket serverSocket = new ServerSocket(9090); while(true) { Socket socket = serverSocket.accept(); new Thread(new Runnable() { @Override public void run() { OutputStream os = null; int connt = 0; try { // 获取Socket的输⼊入流, 就是通过这个输入流获得客户端发送给服务器的数据 InputStream inputStream = socket.getInputStream(); File f = new File("D:/","1.mp4"); while(f.exists()) { f = new File("D:/","1("+(++connt)+").mp4"); } os = new FileOutputStream(f); byte[] bytes = new byte[2048]; int a = inputStream.read(bytes); while(a != -1) { os.write(bytes,0,a); a = inputStream.read(bytes); } } catch (IOException e) { e.printStackTrace(); }finally { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } }).start(); // 接受客户端的连接,产生一个Socket } } }浏览器 :IE
服务器:Tomcat
自定义服务端
public class MyTomcat { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9090); Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); byte[] buf = new byte[2048]; int len = in.read(buf); String text = new String(buf,0,len); System.out.println(text); StringBuffer reply = new StringBuffer(); // 必须添加的响应头 reply.append("HTTP/1.1 200 OK\\nContent-type:text/html\n\n");// 必须添加的响应头 InputStream is = new FileInputStream("D:/2.html"); buf = new byte[2048]; len = is.read(buf);//返回读取到的有效字节数 while(len != -1) { reply.append(new String(buf,0,len)); len = is.read(buf); } OutputStream outputStream = socket.getOutputStream(); //此处不修改编码格式,需要html中指定 outputStream.write(reply.toString().getBytes("GB2312")); socket.close(); serverSocket.close(); } }使用已有的客户端IE,了解一下客户端给服务端发了什么请求?
客户端发送的请求是:
//以下是请求行 //格式为:请求方式 / 请求的资源路径 / http协议版本。 GET / HTTP/1.1 //以下是请求消息头 //格式为:属性名:属性值 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */* //支持解析的数据类型 Accept-Language: zh-cn,zu;q=0.5 //支持的语言 Accept-Encoding: gzip, deflate //支持的压缩包 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2)//用户信息 Host: 127.0.0.1:9090 //要访问的主机 //Host: www.huyouni.com:9090 Connection: Keep-Alive(或者close) //空行 //请求体(比如注册信息)。自定义客户端
public class MyBrowser { public static void main(String[] args) throws UnknownHostException, IOException { Socket s = new Socket("192.168.1.100",8080); //模拟浏览器,给tomcat服务端发送符合http协议的请求消息。 PrintWriter out = new PrintWriter(s.getOutputStream(),true); out.println("GET /myweb/1.html HTTP/1.1"); out.println("Accept: */*"); out.println("Host: 192.168.1.100:8080"); out.println("Connection: close"); out.println(); out.println(); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); String str =new String(buf,0,len); System.out.println(str); s.close(); //http://192.168.1.100:8080/myweb/1.html } }服务端发回应答消息。
//以下是应答行 //http的协议版本 应答状态码 应答状态描述信息 HTTP/1.1 200 OK //以下是应答消息属性信息 //属性名:属性值 Server: Apache-Coyote/1.1 ETag: W/"199-1323480176984" Last-Modified: Sat, 10 Dec 2011 01:22:56 GMT Content-Type: text/html Content-Length: 199 Date: Fri, 11 May 2012 07:51:39 GMT Connection: close //空行 //应答体。 <html> <head> <title>这是我的网页</title> </head> <body> <h1>欢迎光临</h1> <font size='5' color="red">这是一个tomcat服务器中的资源。是一个html网页。</font> </body> </html>URL对象创建 URL url = new URL("http://192.168.1.100:8080/myweb/1.html?name=list");
常用方法
StringgetFile()获取此 URL的文件名StringgetHost()获取此 URL的主机名(如适用)StringgetPath()获取此 URL的路径部分intgetPort() 获取此URL的端口号StringgetProtocol()获取此 URL的协议名称StringgetQuery()获取此 URL的查询部分URLConnectionopenConnection()返回一个URLConnection实例,表示与URL引用的远程对象的URLInputStreamopenStream()打开与此 URL ,并返回一个 InputStream ,以便从该连接读取,相当于URLConnection conn = url.openConnection(); InputStream in = conn.getInputStream();的简写URL统一资源定位器简易浏览器
String str_url = "http://192.168.1.100:8080/myweb/1.html"; URL url = new URL(str_url); //获取url对象的Url连接器对象。将连接封装成了对象:java中内置的可以解析的具体协议的对象+socket. URLConnection conn = url.openConnection(); InputStream in = conn.getInputStream(); //InputStream in = url.openStream(); byte[] buf = new byte[1024]; int len = in.read(buf); String text = new String(buf,0,len); System.out.println(text); in.close();C/S client/server 特点: 该结构的软件,客户端和服务端都需要编写。 可发成本较高,维护较为麻烦。 好处: 客户端在本地可以分担一部分运算。
B/S browser/server 特点: 该结构的软件,只开发服务器端,不开发客户端,因为客户端直接由浏览器取代。 开发成本相对低,维护更为简单。 缺点: 所有运算都要在服务端完成。