网络编程
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了网络编程,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含10915字,纯文字阅读大概需要16分钟。
内容图文
网络编程就是通过网络协议在多个计算机网络连接进行通信。
java.net 包中提供了两种常见的网络协议的支持:
-
TCP:TCP 是通过建立连接,进行通信的安全的网络协议,被称 TCP / IP,安全但效率比较低。
-
UDP:UDP 一个无连接的协议。应用程序之间通过发送数据包进行通信,可能会丢包,不安全但效率高。
UDP
UDP协议编程。
服务端
1,首先需要通过DatagramSocket绑定本地的一个端口,绑定后其他计算机才能通过本机IP地址加端口来访问。
2,接受数据,UDP编程都是通过发送包裹来传输信息,所以需要准备一个包裹容器,通过DatagramPacket类建立一个发送或接受信息的包裹
接收数据包,这是一个接受的包裹,所以只需要指定多少大小的包裹就可以了
public DatagramPacket(byte[] buf,int length)
发送数据包发送的包裹还需要指定发送的IP和端口
public DatagramPacket(byte[] buf,int offset,int length,socketaddress address)
buf
- 分组数据。offset
- 分组数据偏移。length
- 分组数据长度。address
- 目标套接字地址(包含类目标IP和端口)
需要注意的是:UDP的包裹都需要通过字节数组进行构建,所以其它的基本类型,对象,文件的传输都需要先转化为字节数组,如何转换后面在讲;
3,接受包裹,通过receive()方法接收,这个方法是阻塞式的,只要接收到包裹后,程序才会向下执行。
4,分析包裹,通过getData()方法获取包裹字节数组数据,接收的肯定是字节数组,所以需要通过字节数组获取数据:
byte[] datas=packet.getData();
代码:
import java.net.DatagramPacket; import java.net.DatagramSocket; public class UdpServer { public static void main(String args[]) throws Exception { System.out.println("接受方启动......"); //1、使用DataframSocket类对象 传入参数指定本地接受端口 DatagramSocket server = new DatagramSocket(6666); //2、准备容器 封装成DatagramPacket包裹 byte[] container = new byte[1024*60]; DatagramPacket packet = new DatagramPacket(container,0,container.length); //3、阻塞式接受包裹receive(DatagramPacket p) server.receive(packet); //4、分析数据 // byte[] getData() // getLength() byte[] datas=packet.getData(); int len = packet.getLength(); System.out.println(new String(datas,0,len)); server.close(); } }
客户端:
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; public class UdpClient { public static void main(String args[]) throws Exception { System.out.println("发送方启动中......"); //1,绑定本地端口,用于发送接收消息 DatagramSocket client= new DatagramSocket(8888); //2,构建数据包 String data="我爱北京天安门"; byte[] datas=data.getBytes(); DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
//发送数据包 client.send(packet); client.close(); } }
如何转换基本类型,文件,对象为字节数组
通过java的IO流,管道流转换;
1,基本类型转换为字节数组;
DatagramSocket client= new DatagramSocket(8888); //1,ByteArrayOutputStream是字节数组流 ByteArrayOutputStream baos = new ByteArrayOutputStream();
//2,给baos字节数组流外面接一个基本类型数据流DataOutputStream就可以通过dos写入基本类型数据,baos流出字节数组了 DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos)); //3,写入基本类型数据 dos.writeUTF("编码辛酸泪"); dos.writeInt(18); dos.writeBoolean(false); dos.writeChar('a'); dos.flush();
//4,通过toByteArray()方法将当前管道的缓存数据返回成字节数组 byte[] datas=baos.toByteArray(); DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666)); client.send(packet); client.close();
2,对象转换为字节数组
对象的转换需要通过ObjectOutputStream或ObjectInputStream来发送和接收对象。为了能够进行传输,这些对象必须是可序列化的(可序列化的对象,它实例化它的类必须实现Serializable接口)。
3,文件转换为字节数组
其实就是通过文件流不断读取数据,写到字节输出流,保存到字节数组中,创建包裹,然后发送;
package net; import java.io.*; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; public class UdpobjClient { public static void main(String args[]) throws Exception { System.out.println("发送方启动中......"); //1、使用DatagramSocket指定端口,创建发送端 DatagramSocket client= new DatagramSocket(8888); //2、准备数据 一定转成字节数组 ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos)); //操作数据类型+数据 File file=new File("src/net/img.png"); byte[] datas=FileToArray(file); DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666)); client.send(packet); client.close(); } private static byte[] FileToArray(File file) throws IOException { byte[] data=null; try { FileInputStream fis= new FileInputStream(file); ByteArrayOutputStream baos= new ByteArrayOutputStream(); int len; byte[] buffer = new byte[1024]; while((len=fis.read(buffer))!=-1) { baos.write(buffer,0,len); } data=baos.toByteArray(); fis.close(); baos.close(); } catch (FileNotFoundException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } return data; } }View Code
如何建立两台同时发送接收消息
加入多线程,将发送端和接收端封装成线程,需要连接就直接开始一个线程,这样就可以同时与多台设备通信了;
import java.io.*; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; public class UdpSend implements Runnable{ private int port; DatagramSocket client; BufferedReader in; DatagramPacket packet; String toIP; int toPort; String data = null; UdpSend(int port,String toIP,int toPort) throws Exception{ this.toIP=toIP; this.toPort=toPort; client= new DatagramSocket(port); in= new BufferedReader(new InputStreamReader(System.in)); } @Override public void run() { // TODO 自动生成的方法存根 while(true) { try { data = in.readLine(); byte[] datas=data.getBytes(); packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(toIP,toPort)); client.send(packet); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } if(data.equals("bye")) { break; } } client.close(); } }发送端
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class UdpReceive implements Runnable{ DatagramSocket server; byte[] container; DatagramPacket packet; String data; UdpReceive(int port) throws SocketException{ server = new DatagramSocket(port); container= new byte[1024*60]; packet = new DatagramPacket(container,0,container.length); } @Override public void run() { // TODO 自动生成的方法存根 while(true) { try { server.receive(packet); byte[] datas=packet.getData(); int len = packet.getLength(); data=new String(datas,0,len); System.out.println(data); if(data.equals("bye")) { break; } } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } server.close(); } }接收端
学生与老师同时发送接收消息;
学生:
public class Student {
public static void main(String args[]) throws Exception {
new Thread(new UdpSend(8888,"localhost", 9999)).start();
new Thread(new UdpReceive(7777)).start();
}
}
老师:
public class Teacher { public static void main(String args[]) throws Exception { new Thread(new UdpSend(5555,"localhost", 7777)).start();; new Thread(new UdpReceive(9999)).start();; } }
TCP
TCP协议分为服务端和客户端,两端的部署有一点不一样;
服务端:
1,服务器实例化一个 ServerSocket 对象,绑定一个端口,用来监听客户端连接;
2,服务器调用 ServerSocket 类的 accept() 方法,该方法将一直阻塞式等待,直到客户端连接到服务器上给定的端口,返回一个Socket对象;
3,通过socket的getInputStream()和getOutputStream()获得与客户端连接的输入输出流,进行通信;
客户端:
1,通过Socket实例化一个与指定主机和端口的服务器连接;
2,通过socket的getInputStream()和getOutputStream()获得与服务器端连接的输入输出流,进行通信;
代码:
服务器:
import java.io.*; import java.net.*; public class server { public static void main(String args[]) throws IOException { ServerSocket server = new ServerSocket(8888); Socket socket = server.accept(); System.out.println("客户端建立连接"); DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); String data; data=in.readUTF(); System.out.println(data); in.close(); socket.close(); } }
客户端:
import java.io.*; import java.net.Socket; import java.net.UnknownHostException; public class client { public static void main(String args[]) throws UnknownHostException, IOException { System.out.println("客户端启动"); Socket client=new Socket("localhost",8888); DataOutputStream out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream())); out.writeUTF("我爱北京天安门"); out.close(); client.close(); } }
服务端运行结果:
客户端运行结果:
加入多线程实现多台计算机通信:
服务端:
import java.io.*; import java.net.*; class clientThread implements Runnable{ Socket socket; DataInputStream in; DataOutputStream out; String data; String uname=null; String upasw=null; public clientThread(Socket socket) throws IOException { this.socket=socket; in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); } @Override public void run() { // TODO 自动生成的方法存根 try { System.out.println("iiiiieeeeeee"); data=in.readUTF(); System.out.println(data); String[] msg=data.split("&"); for(String info:msg) { String[] userinfo=info.split("="); if(userinfo[0].equals("用户名")) { System.out.println("用户名:"+userinfo[1]); uname=userinfo[1]; } else if(userinfo[0].equals("密码")) { System.out.println("密码:"+userinfo[1]); upasw=userinfo[1]; } // System.out.println(uname+"--->"+upasw); } if(uname.equals("ZDL")&&upasw.equals("7820170")) { out.writeUTF("登录成功,欢迎回来"); out.flush(); } else { out.writeUTF("登录失败"); out.flush(); } // in.close(); // out.close(); // socket.close(); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } System.out.println(data); } } public class Loginserver { public static void main(String args[]) throws IOException { ServerSocket server = new ServerSocket(8888); Socket socket; boolean isrunning=true; while(isrunning) { socket = server.accept(); System.out.println("一个客户端建立连接"); new Thread(new clientThread(socket)).start(); } server.close(); } }View Code
客户端:
package tcp; import java.io.*; import java.net.Socket; import java.net.UnknownHostException; public class Loginclient { public static void main(String args[]) throws UnknownHostException, IOException { System.out.println("客户端启动"); String uname; String upasw; Socket client=new Socket("localhost",8888); // DataInputStream in = new DataInputStream(new BufferedInputStream(System.in)); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.print("请输入用户名:"); uname=in.readLine(); // System.out.println("1"); System.out.print("请输入用户密码:"); upasw=in.readLine(); // System.out.println("1"); DataOutputStream out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream())); out.writeUTF("用户名="+uname+"&密码="+upasw); // System.out.println("1"); out.flush(); DataInputStream input = new DataInputStream(new BufferedInputStream(client.getInputStream())); String response=input.readUTF(); System.out.println(response); out.close(); client.close(); } }View Code
内容总结
以上是互联网集市为您收集整理的网络编程全部内容,希望文章能够帮你解决网络编程所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。