socket通信学习笔记





TCP/IP是目前世界上应用最为广泛的协议

是以TCP/IP为基础的不同层次上多个协议的集合

也称:TCP/IP协议族 或TCP/IP协议栈

TCP:传输控制协议

IP:互联网协议


端口号:用户区分不同的应用程序;端口号范围为0~65535,其中0~1023为系统保留;

IP地址和端口号组成了所谓的Socket,Socket是网络上运行的程序之间双向通信连接的终结点,是TCP和UDP的基础。

http:80

ftp:21

telnet:23

Java中的网络支持:

1.InetAddress:用户标识网络上的硬件资源;

2.URL:统一资源定位符,通过URL可以直接读取或写入网络上的数据。

3.Socket:使用TCP协议实现网络通信的Socket相关的类;

4.Datagram:使用UDP协议,将数据保存在数据报中,通过网络进行通信

InetAddress类:InetAddress类用户标识网络上的硬件资源,标识互联网协议(IP)地址。

<span style="font-size:18px;">//获取本级的InetAddress实例
		InetAddress address = InetAddress.getLocalHost();
		System.out.println("计算机名:"+address.getHostName());
		System.out.println("IP地址:"+address.getHostAddress());
		byte[] bytes = address.getAddress(); //获取字节数组形式的IP地址
		System.out.println("字节数组形式的IP"+Arrays.toString(bytes));
		System.out.println(address);
		
		//根据主机名获取InetAddress实例
		//InetAddress address2 = InetAddress.getByName("lihf");
		InetAddress address2 = InetAddress.getByName("10.10.0.160");
		System.out.println("计算机名:"+address2.getHostName());
		System.out.println("IP地址:"+address2.getHostAddress());</span>
URL:

1.URL(Uniform Resource Locator)统一资源定位符,表示Internet上某一资源的地址

2.URL由两部分组成:协议名称和资源名称,中间用冒号隔开。

3.在java.net包中,提供了URL类来标识URL。

<span style="font-size:18px;">public static void main(String[] args) {
		//创建一个URL的实例
		try {
			URL test = new URL("http://www.lihf.com");
			//?标示参数,#后面标示锚点
			URL url = new URL(test,"/index.html?username=lihf#test");
			System.out.println("协议:"+url.getProtocol());
			System.out.println("主机:"+url.getHost());
			//如果未指定端口号,则使用默认端口号,此时getPort方法返回值为-1
			System.out.println("端口:"+url.getPort());
			System.out.println("文件路径:"+url.getPath());
			System.out.println("文件名:"+url.getFile());
			System.out.println("相对路径:"+url.getRef());
			System.out.println("查询字符串:"+url.getQuery());
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}</span>
使用URL读取网页内容

1.通过URL对象的openStream()方法可以得到制定资源的输入流

2.通过输入流读取或者访问网络上的资源

<span style="font-size:18px;">public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			//创建URL的实例
			URL url= new URL("http://www.baidu.com");
			//通过URL的openStream方法获取URL对象所表示的资源的字节输入流
			InputStream is =  url.openStream();
			//字节输入流转换为字符输入流
			InputStreamReader isr = new InputStreamReader(is,"UTF-8");
			//为字符输入流添加缓冲
			BufferedReader br = new BufferedReader(isr);
			String data = br.readLine(); //读取数据
			while(data!=null){
				System.out.println(data);
				data=br.readLine();
			}
			br.close();
			isr.close();
			is.close();
			
			
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}</span>
Socket通信:TCP协议是面向连接、可靠的、有序的、以字节流的方式发送数据

基于TCP协议实现网络通信的类

客户端的Socket类

服务器端的serverSocket类

Socket通信模型:


Socket通信实现步骤

1.创建serverSocket和Socket

2.打开连接到Socket的输入/输出流

3.按照协议对Socket进行读写操作

4.关闭输入输出流,关闭Socket

实现通信

服务器端:

1、创建ServleSocket对象,绑定监听端口

2、通过accept()方法监听客户端请求

3、连接建立后,通过输入流读取客户端发送的请求信息

4、通过输出流向客户端发送响应信息

5、关闭相关资源

客户端:

1、创建Socket对象,指明需要连接的服务器的地址和端口号

2、连接建立后,通过输出流向服务器端发送请求信息

3、通过输入流获取服务区响应的信息

4、关闭相关资源

<span style="font-size:18px;">/*
 * 基于TCP协议的Socket通信,实现用户登陆
 * 服务器端
 */
public class Server {
	public static void main(String[] args) {
		try {
			//1、创建一个ServleSocket,指定绑定的端口,并监听端口
			ServerSocket serverSocket = new ServerSocket(8888);
			//2、调用accept方法开始监听,等待客户端连接
			System.out.println("**服务器即将启动,等待客户端的链接***");
			Socket socket = serverSocket.accept();
			//3、获取输入流,用来读取客户端发送的登陆信息
			InputStream is = socket.getInputStream();  //字节输入流
			InputStreamReader isr = new InputStreamReader(is); //将字节流转换为字符流
			BufferedReader br = new BufferedReader(isr); //为输入流添加缓冲
			String info = null;
			while((info=br.readLine())!=null){
				System.out.println("我是服务器,客户端说:"+info);
			}
			socket.shutdownInput();//关闭输入流
			//4、获取输出流,响应客户端
			OutputStream os = socket.getOutputStream();
			PrintWriter pw = new PrintWriter(os);
			pw.write("欢迎你!");
			pw.flush(); //刷新缓存
			//5、关闭资源
			pw.close();
			os.close();
			br.close();
			isr.close();
			is.close();
			socket.close();
			serverSocket.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}</span>

<span style="font-size:18px;">/*
 *客户端
 */
public class Client {
	public static void main(String[] args) {
		try {
			//1、创建Socket,指定服务器地址和端口
			Socket socket = new Socket("localhost", 8888);
			//2、获取输出流用来向服务器端发送登陆信息
			OutputStream os = socket.getOutputStream();//字节输出流
			PrintWriter pw = new PrintWriter(os); //将输出流包装为打印流
			pw.write("用户名:admin;密码:123");
			pw.flush();
			socket.shutdownOutput(); //关闭输出流
			//3、获取输入流,读取服务器端的响应信息
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String info = null;
			while((info=br.readLine())!=null){
				System.out.println("我是客户端,服务器说:"+info);
			}
			//4、关闭资源
			br.close();
			is.close();
			pw.close();
			os.close();
			socket.close();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}</span>
使用多线程实现多客户端的通信

应用多线程来实现服务器与多客户端之间的通信

基本步骤:

1、服务器端创建ServerSocket,循环调用accept()等待客户端连接

2、客户端创建一个socket并请求和服务器端连接

3、服务器端接受客户端请求,创建socket与该客户建立专线连接

4、建立连接的两个socket在一个单独的线程上对话

5、服务器端继续等待新的链接

<span style="font-size:18px;">/*
 * 服务器端线程处理类
 */
public class ServerThread extends Thread {

	//和本线程相关的Socket
	Socket socket = null;
	public ServerThread(Socket socket){
		this.socket = socket;
	}
	//线程执行操作,响应客户端请求
	public void run(){
		
		InputStream is =null;
		InputStreamReader isr=null;
		BufferedReader br=null;
		
		OutputStream os=null;
		PrintWriter pw=null;
		try {
			//3、获取输入流,用来读取客户端发送的登陆信息
			is = socket.getInputStream();
			isr = new InputStreamReader(is);
			br = new BufferedReader(isr);
			String info = null;
			while((info=br.readLine())!=null){
				System.out.println("我是服务器,客户端说:"+info);
			}
			socket.shutdownInput();//关闭输入流
			//4、获取输出流,响应客户端
			os = socket.getOutputStream();
			pw = new PrintWriter(os);
			pw.write("欢迎你!");
			pw.flush(); //刷新缓存
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				//关闭资源
				if(pw!=null){				
					pw.close();
				}
				if(os!=null){				
					os.close();
				}
				if(br!=null){				
					br.close();
				}
				if(isr!=null){				
					isr.close();
				}
				if(is!=null){				
					is.close();
				}
				if(socket!=null){
					socket.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
}</span>
<span style="font-size:18px;">/*
 * 基于TCP协议的Socket通信,实现用户登陆
 * 服务器端
 */
public class Server {
	public static void main(String[] args) {
		try {
			//创建一个ServleSocket,指定绑定的端口,并监听端口
			ServerSocket serverSocket = new ServerSocket(8888);
			//记录客户端连接数量
			int count =0;
			System.out.println("**服务器即将启动,等待客户端的链接***");
			Socket socket = null;
			//循环监听等待客户端的链接
			while(true){				
				//调用accept方法开始监听,等待客户端连接
				socket = serverSocket.accept();
				//创建一个新的线程
				ServerThread serverThread = new ServerThread(socket);
				//启动线程
				serverThread.start();
				count++;
				System.out.println("客户端的数量:"+count);
				InetAddress address = socket.getInetAddress();
				System.out.println("当前客户端的IP地址:"+address.getHostAddress());
			} 
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}</span>

客户端代码不变!

Socket实现UDP编程

DataGramPacket

UDP编程:UDP协议(用户数据报协议)是无连接、不可靠的、无序的

进行数据传输时,首先需要将要传输的数据定义成数据报(DataGram),在数据报中指明数据所要达到的Socket(主机地址和端口号),然后再将数据报发送出去。

DatagramPacket:数据报包

DatagramSocket:进行端到端通信的类

服务器端实现步骤:

1、创建DatagramSocket,指定端口号

2、创建DataGramPacket,用来接收客户端发送的数据

3、接收客户端发送的数据信息

4、读取数据

客户端实现步骤:

1、定义发送信息

2、创建DatagramPacket,包含将要发送的信息

3、创建DatagramSocket

4、发送数据

<span style="font-size:18px;">/*
 * 服务器端,实现基于UDP的用户登陆
 */
public class UDPServer {

	public static void main(String[] args) throws IOException {
		/*
		 * 接受客户端发送的数据
		 */
		//1、创建服务器端DatagramSocket,指定端口号
		DatagramSocket socket = new DatagramSocket(8800);
		//2、创建数据报,用来接收客户端发送的数据
		byte[] data = new byte[1024];//创建字节数组,指定接收的数据报的大小
		DatagramPacket packet = new DatagramPacket(data, data.length);
		//3、接收客户端发送的数据
		System.out.println("*******服务器端已经启动,等待客户端发送数据**********");
		socket.receive(packet); //此方法在接受数据报之前一直阻塞
		//4、读取数据
		String info = new String(data,0,packet.getLength());
		System.out.println("我是服务器,客户端说:"+info);
		/*
		 * 向客户端响应数据
		 */
		//1、定义客户端的地址、端口号、数据
		InetAddress address = packet.getAddress();
		int port = packet.getPort();
		byte[] data2 = "欢迎您!".getBytes();
		//2、创建数据报,包含响应数据信息
		DatagramPacket packet2 = new DatagramPacket(data2,data2.length, address, port);
		//3、响应客户端
		socket.send(packet2);
		//4、关闭资源
		socket.close();
	}
}</span>
<span style="font-size:18px;">/*
 * 客户端
 */
public class UDPClient {
	public static void main(String[] args) throws IOException {
		/*
		 * 向服务器端发送数据
		 */
		//1、定义服务器的地址、端口号以及相应发送数据
		InetAddress address = InetAddress.getByName("localhost");
		int port = 8800;
		byte[] data = "用户名:admin;密码:124".getBytes();
		//2、创建数据报,包含发送的数据信息
		DatagramPacket packet = new DatagramPacket(data, data.length, address,port);
		//3、创建DataGramSocket对象
		DatagramSocket socket = new DatagramSocket();
		//4、向服务器端发送数据
		socket.send(packet);
		/*
		 * 接受服务器端响应的数据
		 */
		//1、创建数据报,接受服务器端响应数据
		byte[] data2 = new byte[1024];
		DatagramPacket packet2 = new DatagramPacket(data2, data2.length);
		//2、接受服务器响应的数据
		socket.receive(packet2);
		//3、读取服务器端响应的数据信息
		String reply = new String(data2,0,packet2.getLength());
		System.out.println("我是客户端,服务器说:"+reply);
		socket.close();
	}
}</span>
UDP应用多线程来实现服务器与多客户端之间的通信
<span style="font-size:18px;">public class UDPServerThread extends Thread {
	DatagramSocket socket = null;
	DatagramPacket packet = null;
	public UDPServerThread(DatagramPacket packet,DatagramSocket socket){
		this.packet = packet;
		this.socket = socket;
	}
	public void run(){
		byte[] data = packet.getData();
		String info = new String(data,0,packet.getLength());
		System.out.println("我是服务器,客户端说:"+info);
		//响应客户端
		InetAddress address = packet.getAddress();
		int port = packet.getPort();
		byte[] data2 = "欢迎您!".getBytes();
		DatagramPacket packet2 = new DatagramPacket(data2, data2.length,address, port);
		try {
			socket.send(packet2);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}</span>
<span style="font-size:18px;">/*
 * 服务器端,实现基于UDP的用户登陆
 */
public class UDPServer {

	public static void main(String[] args) throws IOException {
		//创建服务器端DatagramSocket,指定端口号
		DatagramSocket socket = new DatagramSocket(8800);
		byte[] data = new byte[1024];//创建字节数组,指定接收的数据报的大小
		int count=0;
		System.out.println("*******服务器端已经启动,等待客户端发送数据**********");
		while(true){
			DatagramPacket packet = new DatagramPacket(data, data.length);
			socket.receive(packet);
			UDPServerThread serverThread = new UDPServerThread(packet, socket);
			serverThread.start();
			count++;
			System.out.println("客户端的数量是"+count);
		}
	}
}</span>
客户端不变!

Socket总结

多线程的优先级:降低优先级

























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值