35、网络编程
网络通讯
1、找到对方IP
2、数据要发送到对方指定的应用程序上,为了标识这些应用,所以给这些网络应用程序用数字尽心标识
3、定义通讯规则,这个通讯规则称为协议,国际组织定义了通用协议:TCP/IP
网络模型
OSI参考模型(应用层、表示层、会话层、传输层、网络层、数据链路层、物理层)
TCP/IP模型(应用层、传输层、网络层、主机至网络层)
IP地址和端口号
IP地址:网络中设备的标识,不易记忆,可用主机名
本地回环地址127.0.0.1,主机名:localhost
端口号:用于标记进程的逻辑地址,不同于进程的标识,有效的端口号范围为0-65535,其中0-1024之间的端口数位一些知名网络服务和应用
传输协议
TCP——传输控制协议(Transmission Control Protocol)是面向连接的通讯协议,建立连接,形成传输数据的通道,在连接中进行大数据量传输,通过三次完成连接,是可靠的协议,需要必须建立连接,效率会稍低
UDP——用户数据报协议(User Datagram Protcol)是无连接通信协议,将数据源和目的封装成数据报中,不需要建立连接,每个数据报的大小限制在64k内,因无连接,是不可靠协议,不需要建立连接,速度快
package days20;
import java.net.*;
public class Ip
{
public static void main(String[]args) throws UnknownHostException
{
InetAddress i=InetAddress.getLocalHost();
System.out.println("本机信息:"+i.toString());
System.out.println("本主机名:"+i.getHostName());
System.out.println("本机IP地址:"+i.getHostAddress());
InetAddress ia=InetAddress.getByName("127.0.0.1");
System.out.println(ia.toString());
InetAddress ic=InetAddress.getByName("www.baidu.com");
System.out.println(ic.toString());
}
}
Socket
Socket是为网络服务提供的一种机制,它是网络驱动层提供给应用程序编程的一个接口,可以把Socket比喻成一个港口的码头,应用程序只要把货物放到港口码头上,就算完成货物的运送,应用程序只需要等待货物到达码头后,把货物取走,Socket在应用程序上的创建,通过一种绑定机制与驱动层数建立联系,告诉自己对应的IP和Port
Socket发送过程
1、产生Socket
2、应用程序调用bind将Socket信息通知给驱动程序
3、应用程序将要发送的信息传送给Socket
4、驱动程序从Socket取出数据并通过网卡发送出去
Socket接收过程
1、产生Socket
2、应用程序调用bind将Socket信息通知给驱动程序
3、驱动程序根据从网卡传送的数据报中指定的目标端口号,将处理后的数据传送到Socket中
4、应用程序从Socket中取出数据
练习代码
需求:通过UDP传输方式,将一段文字发送出去
思路:1、建立UDP Socket连接,创建UDP服务通过DatagramSocket对象
2、提供数据将数据封装到数据包中DatagramPacket(byte[] buf, int length, InetAddress address, int port)
3、通过Socket服务的发送功能——send方法,将数据包发送出去
4、关闭资源
package days20;
import java.net.*;
public class UDPSend
{
public static void main(String[]args) throws Exception
{
InetAddress i=InetAddress.getLocalHost();
String host=i.getHostName();
DatagramSocket ds=new DatagramSocket();
byte[]buf="你好".getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length,i.getByName(host),10000);
ds.send(dp);
ds.close();
}
}
需求:通过UDP方式,用于接收UDP协议数据并处理
思路:1、创建UDPSocket服务,建立端点
2、定义一个数据包,因为要存储接收到的字节数据,因为数据包对象中有更多的功 能可以提取字节数据中不同的数据信息
3、通过Socket服务的receive方法将收到的数据存入已经定义好的数据包中
4、通过数据包对象特有的功能,将这些不同的数据取出,打印在控制台上
5、关闭资源
package days20;
import java.net.*;
public class UDPRece
{
public static void main(String[]args)throws Exception
{
DatagramSocket ds=new DatagramSocket(10000);
byte[]buf=new byte[1024*1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip=dp.getAddress().getHostName();
String data=new String(dp.getData(),0,dp.getLength());
int port=dp.getPort();
System.out.println(ip+port+"::"+data);
}
}
注意:
在定义UDP时通常会监听一个端口,其实就是给这个接收网络应用程序定义的数字标识,方便于明确哪些数据过来设应用程序可以处理
运行时命令提示符敲start
package days20;
import java.net.*;
import java.io.*;
public class UDPs
{
public static void main(String[]args)throws Exception
{
DatagramSocket ds=new DatagramSocket();
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
String line=null;
InetAddress i=InetAddress.getLocalHost();
String host=i.getHostName();
while((line=bufr.readLine())!=null)
{
if("bye".equals(line))
break;
byte[]buf=line.getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length,i.getByName(host),10000);
ds.send(dp);
}
ds.close();
}
}
package days20;
import java.net.*;
public class UDPss
{
public static void main(String[]args)throws Exception
{
DatagramSocket ds=new DatagramSocket(10000);
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方法,而且这两个方法要封装到不同的类中
package days20;
import java.io.*;
import java.net.*;
class Sends implements Runnable
{
private DatagramSocket ds;
public Sends(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
InetAddress i=InetAddress.getLocalHost();
String host=i.getHostName();
while((line=bufr.readLine())!=null)
{
byte[] buf = line.getBytes();
DatagramPacket dp =
new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10023);
ds.send(dp);
if("886".equals(line))
break;
}
}
catch (Exception e)
{
throw new RuntimeException("发送端失败");
}
}
}
class Rece implements Runnable
{
private 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();
String msg=dp.getAddress().getHostName();
String data = new String(dp.getData(),0,dp.getLength());
if("886".equals(data))
{
System.out.println(msg+":"+ip+"....离开聊天室");
break;
}
System.out.println();
System.out.println(msg+":"+ip);
System.out.println(data);
}
}
catch (Exception e)
{
throw new RuntimeException("接收端失败");
}
}
}
class ChatDemo
{
public static void main(String[] args) throws Exception
{
DatagramSocket SendsSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10023);
new Thread(new Sends(SendsSocket)).start();
new Thread(new Rece(receSocket)).start();
}
TCP网络程序的工作原理
(1)客户端发出连接
(2)服务端接受请求并创建的新的Socket
(3)两个Socket建立专线连接
TCP客户端程序与TCP服务端程序的交互过程
(1)服务器程序创建一个ServerSocket,然后调用accept方法等待客户来连接
(2)客户端程序创建一个Socket并请求与服务器建立连接
(3)服务器接收客户的连接请求,并创建一个新的Socket与该客户建立专线连接
(4)建立了连接的两个Socket在一个单独的线程(由服务器创建)上对话
(5)服务器开始等待新的连接请求,当新的连接请求到达时重复步骤(2)岛步骤(5)的过程
演示TCP传输
(1)TCP分客户端和服务端
(2)客户端对应的对象是Socket
(3)服务端对应的对象是ServerSocket
客户端:通过查阅Socket对象,发现该对象建立时,就可以连接指定的主机,因为TCP是面向连接的,所以在建立Socket连接时,就要有服务端存在,并连接成功,形成通路后,在该通道进行数据的传输
需求:给服务端发送一个文本数据
创建Socket服务,并指定要连接的主机和端口
package days21;
import java.io.*;
import java.net.*;
public class TCPClient
{
public static void main(String[]args) throws UnknownHostException, IOException
{
Socket s=new Socket("192.168.1.100",10004);
OutputStream out=s.getOutputStream();
out.write("tcp".getBytes());
s.close();
}
}
需求:定义端点接收数据并打印在控制台上
服务端:1、建立服务端的Socket服务,ServerSocket(),并监听一个窗口
2、获取连接客户端对象,通过ServerSocket accept来完成,没有连接就会等,所以这个连接是阻塞式的
3、客户端如果发过来数据,那么服务端要使用对应的客户端对象并获取客户端的读取流来读取发送过来的数据并打印在控制台上
4、关闭服务端
package days21;
import java.net.*;
import java.io.*;
public class TCPServer
{
public static void main(String[]args) throws IOException
{
ServerSocket ss=new ServerSocket(10004);
Socket s=ss.accept();
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip);
InputStream in=s.getInputStream();
byte[]buf=new byte[1024];
int len=in.read(buf);
System.out.println(new String(buf,0,len));
s.close();
}
}