java 网络编程(Socket) TCP/UDP 总结案例

Posted 牧小农

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 网络编程(Socket) TCP/UDP 总结案例相关的知识,希望对你有一定的参考价值。

网络编程:关注的是底层的数据传输

网页编程:数据的展示



1、基本概念


一、网络:将不同的计算机连接在一起局域网 城域网 互联网

二、地址:Ip地址确定网络上的绝对的地址位置   房子的地址

三、端口号(相当于房门):区分计算机上的软件 相当于房门两个字节0~65535 共65536个

1、 同一个协议下,端口号不能重复,不同的协议下可以重复

2、 1024以下的端口不要使用 80-->http 21-->ftp

四、资源定位 URL 统一资源定位 URI:统一资源

五、数据的传输

1、 协议:TCP UDP协议(重点的)

1)、TCP(transfer control protocol):必须先建立连接 先连接在通信 电话 类似于三次握手 面向连接 安全可靠 效率相对低下

 

2)、UDP(UserDatagramProtocol):类似于发短信 非面向连接 效率高


现在一般是将两者结合使用,底层一些不重要的数据使用UDP传输

2、 传输

1、 先封装

2、 后拆分



3、数据封装拆分


1、 InetAddress InetSocketAddress

2、 URL

3、 TCP:serverSocket(建立在服务器上)  Socket(建立在客户端上)

4、 UDP: DatagramSocket DatagramPacket

1、InetAddress:封装IP及DNS

方法:

getHostAddress() 返回ip地址

getHostName() 返回域名|本机为计算机名

InetAddress.getLocalHost();//本机

InetAddress.getByName(“IP地址|域名”);

2、InetSocketAddress:封装端口

1):创建对象:

InetSocketAddress(String hostname,int port)

InetSocketAddress(InetAddress addr,intport)

2):方法:

getAdddress()

getHostName()

getPort()

<span style="font-size:18px;">package com.net.ip;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 没有封装端口
 * @author lyy
 *
 */
public class InetDemo1 {
	
	public static void main(String[] args) throws UnknownHostException {
		//使用getLoaclHost方法创建InetAddress对象
		InetAddress addr = InetAddress.getLocalHost();
		System.out.println(addr.getHostAddress());//返回ip地址
		System.out.println(addr.getHostName());//输入计算机名
		//根据域名得到InetAddress对象
		addr = InetAddress.getByName("www.163.com");
		System.out.println(addr.getHostAddress());//返回服务器的ip地址61.163.117.65
		System.out.println(addr.getHostName()); //输出 www.163.com
		//根据ip得到InetAddress对象
		addr = InetAddress.getByName("61.163.117.65");//如果ip地址存在而且DNS帮你解析了,那么getHostName()这个方法返回的就是www.163.com ,否则输出Ip地址
		System.out.println(addr.getHostAddress());//返回163的服务器的ip
		System.out.println(addr.getHostName());//输入Ip而不是域名,如果这个Ip地址不存在
	
	
	}
	</span>
}



<span style="font-size:18px;">package com.net.ip;

import java.net.*;

/**
 * 封装端口:在InetAddress基础上+端口
 * @author lyy
 *
 */
public class InetSocketDemo1 {

		public static void main(String[] args) throws UnknownHostException {
			InetSocketAddress address = new InetSocketAddress("127.0.0.1", 9999);
			address= new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999);
			System.out.println(address.getHostName());
			System.out.println(address.getPort());
			InetAddress addr = address.getAddress();
			System.out.println(addr.getHostAddress());//返回ip地址
			System.out.println(addr.getHostName());//输入计算机名
			
			
		}
	
}</span>


3、网络爬虫原理

URI(Uniform resource identifier) 统一资源标识符,用唯一的标识一个资源

URL(Uniform resource Locator)统一资源定位器,他是一种具体的URI

四部分组成:协议存放资源的主机域名端口 资源文件名(/)

 URL:

一、创建

URI(String str)//绝对路径构建

URI(URL context,String spec)//相对路径构建

二、方法:

System.out.println("协议:"+url.getProtocol());

System.out.println("域名:"+url.getHost());

System.out.println("端口:"+url.getPort());

System.out.println("资源:"+url.getFile());

System.out.println("相对路径资源:"+url.getPath());

System.out.println("锚点:"+url.getRef());//锚点

System.out.println("参数:"+url.getQuery());//参数:存在锚点回返Null 如果不存在返回参数


<span style="font-size:18px;">package com.net.url;

import java.net.*;

public class URLDemo1 {
	public static void main(String[] args) throws MalformedURLException {
		//绝对路径构建
		URL url = new URL("http://www.baidu.com:80/index.html#aa?uname=lyy");
		System.out.println("协议:"+url.getProtocol());
		System.out.println("域名:"+url.getHost());
		System.out.println("端口:"+url.getPort());
		System.out.println("资源:"+url.getFile());
		System.out.println("相对路径资源:"+url.getPath());
		System.out.println("锚点:"+url.getRef());//锚点
		System.out.println("参数:"+url.getQuery());//参数 :存在锚点 返回Null 如果不存在返回参数
		
		
		
		
		
		//相对路径构建
		url = new URL("http://www.baidu.com:80/a/");
		url = new URL(url,"b.txt");//相对路径
		System.out.println(url.toString());
	}
}<strong>
</strong></span>




4、通过流读取数据——OpenStream()


package com.net.url;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.*;

/**
 * 获取资源:源代码
 * @author lyy
 * 
 */
public class URLDemo2 {

	public static void main(String[] args) throws IOException {
		URL url = new URL("http://www.baidu.com/");//主页默认资源
	
		//获取资源 网络流
//		InputStream is = url.openStream();
//		byte[] flush = new byte[1024];
//		int len = 0;
//		while(-1 != (len = is.read(flush))){
//			System.out.println(new String(flush,0,len));
//		}
//		is.close();
		
		BufferedReader br = 
				new BufferedReader(new InputStreamReader(url.openStream(),"utf-8"));
		BufferedWriter bw = 
				new BufferedWriter(new OutputStreamWriter(new FileOutputStream("baidu.html"),"utf-8"));
		
		String msg = null;
		while((msg = br.readLine()) != null){
			bw.append(msg);
			bw.newLine();
			
		}
		bw.flush();
		br.close();
		bw.close();
	}

}


5、UDP通信

UDP:以数据为中心 非面向连接 不安全 数据可能丢失 效率高

一、类 DatagramSocketDatagramPacket

1、 客户端:

1)、创建客户端DatagramSocket 类 +指定端口

2)、准备数据字节数组

3)、打包 datagramPacket  + 服务器地址和端口

4)、发送

5)、释放资源

 

2、 服务端

a)      创建服务端 DatagramSocket类 +指定端口

b)      准备接收的容器字节数组 封装datagramPacket 

c)       包接收数据

d)      分析数据

e)      释放资源

 

典型的b/s 先从服务器下载源到浏览器(客户端)


<span style="font-size:18px;">package com.net.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * 服务端
 * 1 创建服务端 + 端口
 * 2 准备接收容器
 * 3 封装成包
 * 4 接收数据
 * 5 分析数据
 * @author lyy
 *
 */
public class MyServer {
		public static void main(String[] args) throws IOException {
//			1 创建服务端 + 端口
			DatagramSocket server = new DatagramSocket(8888);
//			2 准备接收容器
			byte[] container = new byte[1024];
//			3 封装成包 DatagramPacket(byte[] buf, int length)
			DatagramPacket packet = new DatagramPacket(container, container.length);
//			4 接收数据
			server.receive(packet);
//			5 分析数据
			byte[] data = packet.getData();
			int len = packet.getLength();
			System.out.println(new String(data,0,len));
			//释放资源
			server.close();
			
		}
}</span>


<span style="font-size:18px;">package com.net.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

/**
 * 客户端
 * 1 创建客户端 + 端口
 * 2 准备数据
 * 3 打包(发送的地点 以及端口)
 * 4 发送
 * 5 释放
 * 
 * @author lyy
 *
 */
public class MyClient {

	public static void main(String[] args) throws IOException {
//		1 创建客户端 + 端口
		DatagramSocket client = new DatagramSocket(6666);
//		2 准备数据
		String msg = "真的爱你";
		byte[] data = msg.getBytes();
//		3 打包(发送的地点 以及端口) DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
		DatagramPacket packet = new DatagramPacket(data, data.length,new InetSocketAddress("localhost",8888));
//	    4 发送
		client.send(packet);
//		5 释放
		client.close();
		
		
	}
	
}
</span>



6、Scoket通信

基于TCP:面向连接安全 可靠 效率低 类似于打电话

一、面向连接:请求 响应 Request——Response

二、Socket 编程

         1、服务器ServerSocket      

         2、客户端 Socket




package com.net.tcp.socket;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 必须先启动服务器 后连接
 * 1 创建服务器 指定端口
 * 2 接收客户端连接
 * 3 发送数据和接收数据
 * 
 *   接收多个客户端
 * @author lyy
 *
 */
public class MultServer {

	public static void main(String[] args) throws IOException {
		//1 创建服务区 指定端口 ServerSocket(int port) 
		ServerSocket server = new ServerSocket(8888);
		// 2 接收客户端连接 阻塞式
		while(true){//死循环 一个accept() 一个客户端
		Socket socket = server.accept();
		System.out.println("一个客户端建立连接");
		// 3 发送数据
		String msg = "欢迎使用";

		DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
		dos.writeUTF(msg);
		dos.flush();
			while(true){
				
			}
		}
	}

}


package com.net.tcp.socket;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 1 创建客户端 必须指定服务器 + 端口 此时连接
 * 			Socket(InetAddress host, int port) 
 *  接收数据 发送数据
 * @author lyy
 *
 */
public class Client {

	public static void main(String[] args) throws UnknownHostException, IOException {
		// 1 、创建客户端 必须指定服务器 + 端口 此时连接
		Socket client = new Socket("192.168.1.112", 8888);
		// 2 接收数据
//		BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
//		String echo = br.readLine();//阻塞式的方法
//		System.out.println(echo);
		DataInputStream dis = new DataInputStream(client.getInputStream());
		String echo = dis.readUTF();
		System.out.println(echo);
		
		
	}
}


7、小案例(强烈建议大家自己敲一遍,很好玩!)

使用的多线程、流以及socket通信原理的方式,创建了一个公众聊天室的demo,进入有系统提示,可以@名字说悄悄话等等,对socket整个知识点稍微了解了更加深入一点点,还是要多消化消化,今天做了一天了,头有点大了,不说了上案例

package com.net.tcp.chat.demo4;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * 创建服务器
 * @author lyy
 *
 */
public class Server {
	private List<MyChanel> all = new ArrayList<MyChanel>();

	public static void main(String[] args) throws IOException {
		new Server().start();
	}
	
	public void start() throws IOException{
		ServerSocket server = new ServerSocket(9999);
		while(true){
			Socket client =  server.accept();
			MyChanel channel = new MyChanel(client);
			all.add(channel);//加入到容器中同意管理
			new Thread(channel).start();//一条道路
		}
	}
	
	/**
	 * 一个客户端一个道路
	 * 1 输入流
	 * 2 输出流
	 * 3 接收数据
	 * 4 发送数据
	 * @author lyy
	 *
	 */
	private class MyChanel implements Runnable{
		private DataInputStream dis;
		private DataOutputStream dos;
		private boolean isRunning = true;
		private String name;
		
		public MyChanel(Socket client) {
			 try {
				dis = new DataInputStream(client.getInputStream());
				 dos = new DataOutputStream(client.getOutputStream());
				 
				 this.name = dis.readUTF();
				 this.send("欢迎你进入聊天室!");
				 sendOthers(this.name+"进入了聊天室",true);
			} catch (IOException e) {
				CloseUtil.closeAll(dis,dos);
				isRunning = false;
			}
		
		}
		
		/**
		 * 读取数据
		 * @return
		 */
		private String receive(){
			String msg = "";
			try {
				msg = dis.readUTF();
			} catch (IOException e) {
				CloseUtil.closeAll(dis);
				isRunning = false;
				all.remove(this);//移除自身
			}
			return msg;
		}
		
		/**
		 * 发送数据
		 */
		public void send(String msg){
			if(null == msg && !msg.equals("")){
				return;
			}
			try {
				dos.writeUTF(msg);
				dos.flush();
			} catch (IOException e) {
//				e.printStackTrace();
				CloseUtil.closeAll(dos);
				isRunning = false;
				all.remove(this);//移除自身
			}
		}
		
		/**
		 * 发送给其他客户端
		 */
		private void sendOthers(String msg,boolean sys){
			System.out.println(msg);
			//是否为私聊 约定
			if(msg.startsWith("@") && msg.indexOf(":") > -1){//表示私聊
				String name = msg.substring(1, msg.indexOf(":"));
				String conetnt = msg.substring(msg.indexOf(":")+1);
				//获取Name
				for (MyChanel other : all) {
					if(other.name.equals(name)){
						other.send(this.name+"对您悄悄说"+conetnt);
					}
				}
			}else{
			
			//遍历容器
			for (MyChanel other : all) {
				if(other == this){
					continue;
				}
				if(sys){//系统信息
					//发送给其他客户端
					other.send("系统信息:"+msg);
				}else{
					//发送给其他客户端
					other.send(this.name+":"+msg);
				}
				
			}
			}
		}
		
		@Override
		public void run() {
			while(isRunning){
				sendOthers(receive(),false);
			}
		}
		
	}
	
}

package com.net.tcp.chat.demo4;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 发送数据线程
 * @author lyy
 *
 */
public class Send implements Runnable{

	//控制台的输入流
	private BufferedReader console;
	//管道输出流
	private DataOutputStream dos;
	//控制线程
	private boolean isRunning = true;
	//名称
	private String name;
	public Send() {
		console = new BufferedReader(new InputStreamReader(System.in));
	}
	
	public Send(Socket client , String name){
		this();
		 try {
			dos = new DataOutputStream(client.getOutputStream());
			this.name = name;
			send(this.name);
		} catch (IOException e) {
//			e.printStackTrace();
			isRunning = false;
			CloseUtil.closeAll(dos,console);
			
		}
	}
	
	//从控制台接收数据
	private  String getMsgFromConsole(){
		try {
			return console.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		
		}
		return "";
	}
	/**
	 * 从控制台接收数据
	 * 发送数据
	 */
	public void send(String msg){
		if(msg != null && !msg.equals("")){
			try {
				dos.writeUTF(msg);
				dos.flush();//强制刷新
			} catch (IOException e) {
//				e.printStackTrace();
				isRunning = false;
				CloseUtil.closeAll(dos,console);
			}
		}
	}
	
	@Override
	public void run() {
		//线程体
		while(isRunning){
			send(getMsgFromConsole());
		}
	}

}


package com.net.tcp.chat.demo4;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

/**
 * 接收线程
 * @author lyy
 *
 */
public class Receive implements Runnable{

	//输入流
	private DataInputStream dis;
	//线程标识
	private boolean isRunning = true;
	
	public Receive() {
	}
	public Receive(Socket client){
		try {
			dis = new DataInputStream(client.getInputStream());
		} catch (IOException e) {
//			e.printStackTrace();
			isRunning = false;
			CloseUtil.closeAll(dis);
		}
	}
	
	/**
	 * 接收数据
	 * @return
	 */
	public String receive(){
		String msg ="";
		try {
			msg = dis.readUTF();
		} catch (IOException e) {
			isRunning = false;
			CloseUtil.closeAll(dis);
		}
		return msg;
	}
	
	@Override
	public void run() {
		//线程体
		while(isRunning){
			System.out.println(receive());
		}
	}

}


<span style="font-size:18px;">package com.net.tcp.chat.demo4;

import java.io.Closeable;
import java.io.IOException;

/**
 * 关闭流的方法
 * @author lyy
 *
 */
public class CloseUtil {
		public static void closeAll(Closeable... io){
			for(Closeable temp :io){
				if(null != temp){
						try {
							temp.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
				}
			}
		}
	</span>
}


<span style="font-size:18px;">package com.net.tcp.chat.demo4;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 创建客户端 发送数据 + 接收数据
 * 写出数据 输出流
 * 读取数据 输入流
 * @author lyy
 * 
 * 输入流和输出流在同一个线程内 彼此独立
 * 
 * 
 *
 */
public class Client {
	
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("请输入名称:");
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String name = br.readLine();
		if(name.equals("")){
			return;
		}
		Socket client = new Socket("localhost", 9999);
		new Thread(new Send(client,name)).start();//一条路径
		new Thread(new Receive(client)).start();//一条路径
	}
	
}
</span>





学习了一天,感觉还是有很大的收获的,需要多消化消化,希望大家也能从中收获一点自己想要的东西,加油!




总结案例下载:http://download.csdn.net/detail/qq_14996421/9527603

以上是关于java 网络编程(Socket) TCP/UDP 总结案例的主要内容,如果未能解决你的问题,请参考以下文章

TCP/UDP套接字 java socket编程实例

Java网络编程Socket服务端和客户端

细说http - tcp - udp - socket - protobuf协议

完全理解TCP/UDPHTTP长连接WebsocketSockJS/Socket.IO以及STOMP的区别和联系

网络编程TCP/UDP(socket编程)

网络编程TCP/UDP(socket编程)