黑马程序员——网络编程(Socket)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

网络编程

概述

Socket来达到进程间的数据传输的编程的就是网络编程。

网络参考模型

概述:描述网络的结构原理和工作原理。

黑马程序员——网络编程(Socket)_第1张图片

  • 1.OSI参考模型:有七层分别是应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。

  • 2.TCP/IP参考模型:有四层分别是应用层、传输层、网际层、数据链路层。

网络通讯要素

1.IP地址:网络中设备的标识,互联网的协议地址,是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。

本地回环地址:127.0.0.1。

2.端口:用于标识进程的逻辑地址,不同进程的标识,不同进程进行通信时会通过端口要找与其通信的程序,程序和端口是一对一的关系。

效端口:0~65535,0~1024系统使用或保留端口。

3.网络协议:指定层上进行数据交换的规则,在网络中的设备(服务器、计算机、交换机、路由器)都能遵守的通信规则。

网络层协议:IP协议、DNS协议(辅助协议)。

传输层协议:TCP、UDP。

UDP:UDP是OSI参考模型中的一种无连接的传输层协议,是一个分包发送的协议。
特点:

1.先将数据及源和目的封装成数据包中,不需要简历连接。

2.每个数据包的大小限制在64k内。

3.不可靠协议。

4.传输速度快。

TCP:TCP是面向连接的基于IP地址的传输层协议。
特点:

1.要建立连接,形成传输数据的通道。

2.在连接中可以进行大数据传输。

3.可靠协议。

4.传输效率稍低。

TCP的三次握手图:


黑马程序员——网络编程(Socket)_第2张图片


Socket
概述
Socket也称为"套接字",是描述IP地址和和端口,是通信链的句柄,程序通过"套接字"向网络发出请求或者应答网络请求。

Socke类型:

1.ServerSocket:用于服务端的套接字。(TCP协议)

2.Socket:用于客户端的套接字。(TCP协议)

3.DatagramSocket:用于UDP协议的套接字。

UDP传输
UDP套接字DatagramSocket
数据包:DatagramPacket

步骤:

  • 1.建立发送端,和接受端。

  • 2.封装数据包。

  • 3.分别调用发送端、接受端的发送、接受方法。

  • 4.关闭Socket。

实例:制作一个聊天室,可以发送信息,也可以接收消息。

/**
 * 创建一个聊天室,可以接收和发送数据。
 * 思路:
 * 1.因为要能接收又能发送,就会需要接收端和发送端同时运行。
 * 2.创建一个专门发送的线程,一个发送的线程。
 * 3.同时运行这两个线程。
 * */
//package SocketDemo;
import java.io.*;
import java.net.*;
class Send implements Runnable //发送线程,实现Runnable接口。
{
	private DatagramSocket ds;
	public Send(DatagramSocket ds)
	{
		this.ds = ds;
	}
	public void run()
	{
		try
		{
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //获取键盘对象并转为字符输入流。
			String line = null;
			while((line=br.readLine()) != null)
			{
				if(line.equals("over"))
					break;
				DatagramPacket dp = new DatagramPacket
						(line.getBytes(), line.length(), InetAddress.getByName("127.0.0.1"), 30000); //创建数据包,把数据,接收的IP地址、端口装包
				ds.send(dp); //发送数据包。
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("发送数据失败!");
		}
		finally
		{
			ds.close(); //关闭套接字。
		}
	}
}
class Rece implements Runnable //接收线程。
{
	DatagramSocket ds;
	public 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 ip = dp.getAddress().getHostAddress(); //获取发送方的IP地址。
				int port = dp.getPort(); //获取发送方的端口。
				String data = new String(dp.getData(),0,dp.getLength()); //取出数据包中的数据。
				System.out.println(ip+":"+port+"发来消息:"+data);
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("接收数据失败!");
		}
		finally
		{
			ds.close(); //关闭套接字。
		}
	}
}
public class UDPDemo
{

	public static void main(String[] args) throws Exception
	{
		DatagramSocket send = new DatagramSocket(); //创建发送套接字。
		DatagramSocket rece = new DatagramSocket(30000); //创建接收套接字。
		new Thread(new Send(send)).start(); //创建并开启发送线程。
		new Thread(new Rece(rece)).start(); //创建并开启接收线程。
	}
}

TCP传输
TCP套接字SocketServerSocket

步骤:

  • 1.建立客户端,和服务端。

  • 2.通过Socket的IO流进行数据传说。

  • 3.关闭Socket。

实例:制作一个能多连接客户端的服务端

服务端:

/**制作一个能多连接客户端的服务端
 * 思路:
 * 1.需要创建ServerSocket。
 * 2.每个客户端请求连接都要产生Socket,但是产生以后主线程又会accept阻塞状态,所以我们需要每个客户端有其处理的线程。
 * 3.因为会多个连接,必须对循环accept方法。
 * 4.创建客户端处理线程类。
 * 5.通过线程while保持客户端和服务端的数据传输。
 * 6.当客户端断开连接时需要关闭其的Socket。
 * */
import java.io.*;
import java.net.*;
class SocketThread implements Runnable //处理每个客户端的线程
{
	private Socket s;
	public SocketThread(Socket s)
	{
		this.s = s;    //把Socket私有。
	}
	public void run()
	{
			System.out.println(s.getInetAddress().getHostAddress()+":"+s.getPort()+"已连接"); //打印连接的客户端信息。
			try
			{
				while(true)
				{
					byte[] buff = new byte[1024];
					s.getInputStream().read(buff);
					if(new String(buff,0,buff.length).equals("over")) //如果客户端发来over,就跳出循环。
						break;
					if(buff.toString()!=null) //判断客户端是否发来消息。
					{
						System.out.println(s.getInetAddress().getHostAddress()
								+":"+s.getPort()+"发来消息"+new String(buff,0,buff.length)); //打印客户端发来的消息。
					}
				}
			}
			catch (Exception e)
			{
				System.out.println(s.getInetAddress().getHostAddress()+":"+s.getPort()+"断开连接"); 
			}
			finally
			{
				try
				{
					s.close(); //关闭Socket。
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
	}
}
public class ServerDemo
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket s = new ServerSocket(20000); //建议ServerSocket服务。
		try
		{
			while(true)
			{
				Socket socket = s.accept(); //阻塞监听端口,有客户端连入时就返回一个Socket对象。
				new Thread(new SocketThread(socket)).start(); //把返回的Socket对象传入创建好的Socket处理线程中,
				                                              //每个客户端与服务端连接的产生的Socket都会专门处理
															  //这个连接的线程。
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("建立连接失败!");
		}
	}
}

客户端

import java.net.*;
import java.io.*;
public class ClinetDemo
{
	public static void main(String[] args) 
	{
		try
		{
			Socket s = new Socket(InetAddress.getByName("127.0.0.1"),20000); //建立能连接指定服务器地址和端口的Socket。
			try
			{
				BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //获取键盘对象。
				String line = null;
				byte[] buff = new byte[1024];
				while(true)
				{
					line = br.readLine(); //读取键盘输入的数据。
					if(line!=null)
					{
						if(line.equals("over")) //判断键盘输入的数据是否为over,是的话跳出循环。
							break;
						s.getOutputStream().write(line.getBytes()); //通过Socket的输出流写入数据。
					}
				}
			}
			catch (Exception e)
			{
				throw new RuntimeException("发送数据失败!");
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("连接不上服务端或与服务端失去连接!");
		}
	}
}

你可能感兴趣的:(java学习笔记)