java 网络编程
2017-04-21 10:22
309 查看
1. 网络模型:
OSI参考模型:(应用层,表示层,会话层,传输层,网络层,数据链路层,物理层)TCP/IP参考模型:(应用层,传输层,网际层,主机至网络层)
2. 网络通讯要素
IP地址本地回环地址:127.0.0.1,主机名:localhost
端口
可用端口:0~65535,其中0~1024是系统使用或者保留端口。
3. Java网络编程常见对象
3.1 根据主机名获取IP地址
//通过主机名获取对应的IP地址 static void netAddressTest1() throws UnknownHostException{ InetAddress inetAddress=InetAddress.getByName("www.baidu.com"); System.out.println("ip地址是"+inetAddress.getHostAddress()); }
4. UDP和TCP的特点
4.1 UDP
将数据及源和目的封装成数据包,不许要建立连接。每个数据包的大小限制在64K内。
因无连接,是不可靠协议。
不需要建立连接,速度快。
4.2 TCP
建立连接,形成传输数据的通道。在连接中进行大数据量传输。
通过三次握手完成连接,是可靠协议。
必须建立连接,效率会稍低。
- 5. UDP的发送和接收
UDP的发送和接收涉及到两个类:DatagramSocket,DatagramPacket。DatagramSocket是一个Socket,发送方可以指定数据发出去时的端口,也可以不指定,会自动分配。接收方的DatagramSocket需要指定那个端口用来接收数据。(目的和源端口必须一致)
DatagramPacket是数据的载体。发送方的DatagramPacket在创建时需要明确接收方的IP地址和端口。
5.1 简单发送
指明接收方的IP和端口,本机用来发送数据的端口,可指定也可不指定。将发送的数据填充到byte[]数组里面,然后用该数组构建一个DatagramPacket对象。
代码:
static void udpSend1() throws Exception{ String hostName="127.0.0.1"; //创建DatagramSocket对象 DatagramSocket datagramSocket=new DatagramSocket(); byte[]datas="haha".getBytes(); //构建DatagramPacket类,其封装了要发送的数据和目的地信息 DatagramPacket datagramPacket=new DatagramPacket(datas, datas.length,InetAddress.getByName(hostName),9999); //发送 datagramSocket.send(datagramPacket); //关闭资源 datagramSocket.close(); }
5.2 简单接收
创建DatagramSocket对象时,必须明确那个端口用来接收数据。创建一个空的字节数组用来接受数据,根据此字节数组创建DatagramPacket对象。
DatagramSocket的receive()方法是阻塞式的。
代码:
static void udpReceive()throws Exception{ //创建Socket,并且必须指明那个端口用来接收消息 DatagramSocket socket=new DatagramSocket(9999); //创建字节数组,存储数据 byte[] data=new byte[1024]; DatagramPacket packet=new DatagramPacket(data, data.length); //接收数据,此方法是阻塞式的,若没有收到消息,会一直等待。 socket.receive(packet); //得到接收到的数据 String datas=new String(packet.getData(),0,packet.getLength()); //得到发送方用来返送数据的端口 int sendPort=packet.getPort(); //得到发送发的IP地址 String sendIP=packet.getAddress().getHostAddress(); System.out.println("收到的数据是 "+datas+"源端口是 "+sendPort+"源IP是 "+sendIP); socket.close(); }
5.3 发送端从键盘输入,接收端一直监听
代码:(键盘接收消息发送)static void udpSendBykeyBoard() throws Exception{ String hostName="127.0.0.1"; //创建DatagramSocket对象 DatagramSocket datagramSocket=new DatagramSocket(); //System.in从键盘录入 BufferedReader reader=new BufferedReader(new InputStreamReader(System.in)); String datas=null; //readLine()是阻塞式的,所以不会造成死循环 while((datas=reader.readLine())!=null){ if(datas.equals("over")) break; byte[] bytes=datas.getBytes(); //构建DatagramPacket类,其封装了要发送的数据和目的地信息 DatagramPacket datagramPacket=new DatagramPacket(bytes, bytes.length,InetAddress.getByName(hostName),9999); //发送 datagramSocket.send(datagramPacket); } //关闭资源 datagramSocket.close(); }
代码:(接收端一直处于接收状态)
static void udpReceive()throws Exception{ //创建Socket,并且必须指明那个端口用来接收消息 DatagramSocket socket=new DatagramSocket(9999); while(true){ //创建字节数组,存储数据 byte[] data=new byte[1024]; DatagramPacket packet=new DatagramPacket(data, data.length); //接收数据,此方法是阻塞式的,若没有收到消息,会一直等待。 socket.receive(packet); //得到接收到的数据 String datas=new String(packet.getData(),0,packet.getLength()); //得到发送方用来返送数据的端口 int sendPort=packet.getPort(); //得到发送发的IP地址 String sendIP=packet.getAddress().getHostAddress(); System.out.println("收到的数据是 "+datas+"源端口是 "+sendPort+"源IP是 "+sendIP); } //socket.close(); }
5.4 用UDP发送和接收文本文件。
发送代码:static void udpSendFile()throws Exception{ String hostName="127.0.0.1";//目标端口 DatagramPacket packet=null; InetAddress address=InetAddress.getByName(hostName); DatagramSocket socket=new DatagramSocket(); //创建字符缓冲读出流 BufferedReader reader=new BufferedReader(new FileReader("D:/code.java")); String data=null; //读取一行数据,然后发送出去。readLine()方法阻塞。 while((data=reader.readLine())!=null){ packet=new DatagramPacket(data.getBytes(), data.getBytes().length,address,9999); socket.send(packet); } //关闭资源 socket.close(); reader.close(); }
接收代码:
static void udpReceiveFile()throws Exception{ //创建一个字符缓冲写入流 BufferedWriter writer=new BufferedWriter(new FileWriter("F:/teset.java")); //创建DatagramSocket对象,9999是监听的端口 DatagramSocket socket=new DatagramSocket(9999); socket.setSoTimeout(4000);//设置超时为4秒,若4秒中没有数据,报超时异常,退出程序 while(true){ byte[] datas=new byte[1024]; DatagramPacket packet=new DatagramPacket(datas, datas.length); //阻塞式方法。所以可以使用while循环 socket.receive(packet); String string=new String(packet.getData(),0,packet.getLength()); System.out.println(string); //每读到一行数据,就写入文件,并且再写入一个换行,刷新。 writer.write(string); writer.newLine(); writer.flush(); } }
6. TCP的发送和接收
TCP分为客户端和服务端。客户端和 服务端的对象也不尽相同。客户端只有一个Socket,用来发送和接收消息。客户端的Socket在创建的时候可以指定服务端的端口和IP地址。
服务端有一个ServerSocket,其accept()方法用来等待客户端连接。ServerSocket创建的时候必须指明监听的端口。
这个Socket对象的使用和客户端的Socket是相同的。其中accept()方法是阻塞式的,只有有客户端连接,才能获取客户端的Socket。一个服务端可以有多个客户端去连接。每连接一个客户端,就创建一个Socket对象
Socket可以获取InputSream用来读取数据,获取OutputStream用来向Socket发送数据
实现客户端向服务端发送一条消息,服务端收到消息后,向该客户端反馈一条消息。
客户端代码:
static void tcpClient()throws Exception{ //创建输入和输出流 InputStream inputStream=null; OutputStream outputStream=null; //创建Socket,客户端需要指明服务端(目的)的IP地址和端口号 Socket socket=new Socket("127.0.0.1",10001); //得到输出流 outputStream=socket.getOutputStream(); //向socket写入数据并且发送 outputStream.write("我是TCP客户端,正在向服务端发消息".getBytes()); //接收服务端发过来的消息 inputStream=socket.getInputStream(); byte[] datas=new byte[1024]; //读取消息 int len=inputStream.read(datas); System.out.println("客户端收到消息--"+new String(datas,0,len)); //关闭资源 socket.close(); }
服务端代码:
static void tcpServer()throws Exception{ InputStream inputStream=null; OutputStream outputStream=null; //创建ServerSocket对象,必须指明监听的端口 ServerSocket serverSocket=new ServerSocket(10001); //该方法是阻塞式方法,每有一个客户端连接,就与之建立一个对应的Socket对象。 Socket socket=serverSocket.accept(); //接收客户端发过来的数据 inputStream=socket.getInputStream(); byte []datas=new byte[1024]; int len=inputStream.read(datas); System.out.println("服务端收到消息--"+new String(datas,0,len)); //向客户端发送数据 outputStream=socket.getOutputStream(); outputStream.write("客户端,你好啊".getBytes()); //关闭资源 socket.close(); //现实中,serverSocket是不能关闭的,因为要一直等待其他客户端的连接 serverSocket.close(); }
6.1 TCP发送和接收图片
发送代码:static void tcpSendPicture() throws Exception{ //创建字节缓冲读出流 BufferedInputStream inputStream=new BufferedInputStream(new FileInputStream("D:/view.jpg")); //创建Socket,客户端需要指明服务端(目的)的IP地址和端口号 Socket socket=new Socket("127.0.0.1",10001); //将socket的输出输出流转换为缓冲输出流。 BufferedOutputStream outputStream=new BufferedOutputStream(socket.getOutputStream()); int datas=0; //注意,datas是读到的数据,而不是数据长度。从文件读到数据缓冲区满了以后,使用outputStream发给服务端 while((datas=inputStream.read())!=-1){ outputStream.write(datas); } //通知服务端发送完毕,服务端收到此消息会停止继续接收数据。 socket.shutdownOutput(); //关闭资源。 socket.close(); inputStream.close(); }
服务端接收代码:
static void tcpReceivePicture() throws Exception{ //创建ServerSocket ,绑定监听端口 ServerSocket serverSocket=new ServerSocket(10001); Socket socket=serverSocket.accept(); //将socket的输入流转换为缓冲输入流,方便读写。 BufferedInputStream inputStream=new BufferedInputStream(socket.getInputStream()); //创建接收数据的IO流对象 BufferedOutputStream outputStream=new BufferedOutputStream(new FileOutputStream("F:/view_copu.jpg")); //datas是读到的数据,不是数据长度。 int datas=0; while((datas=inputStream.read())!=-1){ outputStream.write(datas); } //关闭资源 serverSocket.close(); serverSocket.close(); outputStream.close(); }
7. URLConnection
代码:static void URLtest() throws Exception{ URL url =new URL("https://www.baidu.com/"); URLConnection urlConnection=url.openConnection(); InputStream inputStream=urlConnection.getInputStream(); byte[] datas=new byte[1024]; int len=0; while((len=inputStream.read(datas))!=-1){ System.out.println(new String(datas,0,len)); } }
相关文章推荐