本示例包括两个客户端UDPClient和MyServer。UDPClient发送数据到MyServer,MyServer负责接收数据。可传输文本、视频、音频、图片等。
最近我在学习这一块,写个例子。
(注:如果要在不同PC间运行,请修改UDPclient中的环回地址为测试server的真实ip地址,并关闭双方的windows defender。2017-04-10)
UDPClient端源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Font; import java.awt.GridLayout; import java.io.File; import java.io.FileInputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Timer; import java.util.TimerTask; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; import javax.swing.SwingConstants; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class UDPClient extends JFrame { private JPanel pane = new JPanel(); //防止jbutton的面板 private JButton button_send= new JButton ( "选择并发送文件" ); private JLabel label_client_ip = new JLabel( "本机ip:" ,JLabel.CENTER); private JLabel label_server_ip = new JLabel( "目标ip:" ,JLabel.CENTER); private JLabel label_client_port = new JLabel( "本机端口:6000" ,JLabel.CENTER); private JLabel label_server_port = new JLabel( "目标端口:10000" ,JLabel.CENTER); private JLabel label_file_state = new JLabel( "文件当前状态:无任务" ,JLabel.CENTER); private InetAddress client_ip = null ; //本机ip private InetAddress server_ip = null ; //目标ip private int client_port; //本机port private int server_port; //目标port最小值 DatagramSocket socket_ack; //监听服务器端返回ack or nak String filename = null ; File file ; //传送的文件 /** * Create the frame. * @param client_name : the title of this application * @param server_ip : destination ip * @param client_port : my port * @param server_port : destination port */ public UDPClient(String client_name ,String ip, int myport, int otherport ) { super (client_name); //程序标题栏 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置关闭窗口操作 setBounds( 100 , 100 , 400 , 500 ); //设置窗口大小 getContentPane().setLayout( new GridLayout ( 6 , 1 , 7 , 7 )); //设置全局字体 Font font = new Font( "楷体" ,Font.PLAIN, 20 ); label_client_ip.setFont(font); label_server_ip.setFont(font); label_client_port.setFont(font); label_server_port.setFont(font); label_file_state.setFont(font); button_send.setBackground(Color.LIGHT_GRAY); button_send.setFont(font); //在面板上放置组件 getContentPane().add(label_client_ip); getContentPane().add(label_server_ip); getContentPane().add(label_client_port); getContentPane().add(label_server_port); getContentPane().add(pane); pane.add(button_send); getContentPane().add(label_file_state); this .setVisible( true ); this .server_port=otherport; //获得目标端口 this .client_port=myport; //获得发送端口 /* * 给button_send增加监听事件addActionListener */ button_send.addActionListener( new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { // 选择要发送的文件 JFileChooser filechooser = new JFileChooser(); int result = filechooser.showOpenDialog(UDPClient. this ); if (result == JFileChooser.APPROVE_OPTION) { try { File file1 = filechooser.getSelectedFile(); //选择的文件 file=file1; try { //将文件名发送过去 String filename1 = file1.getName(); // 文件名 String tip = "有文件,请接收:" + filename1; byte [] fileNameBuf = tip.getBytes(); // 字节buf DatagramSocket socket = new DatagramSocket(); DatagramPacket packet = new DatagramPacket( //封装packet fileNameBuf, fileNameBuf.length, UDPClient. this .server_ip, UDPClient. this .server_port); socket.send(packet); //发送 System.out.println( new String(packet.getData())); //socket.close(); UDPClient. this .label_file_state.setText( "文件当前状态:文件正在传输..." ); //将文件写入内存 FileInputStream fis= new FileInputStream(file); //发送文件长度 int filelen=fis.available(); String filelenStr= "" +filelen; byte [] filelenBuf=filelenStr.getBytes(); //DatagramSocket socket = new DatagramSocket(); packet = new DatagramPacket(filelenBuf,filelenBuf.length,server_ip,UDPClient. this .server_port+ 1 ); socket.send(packet); System.out.println( new String(packet.getData())); //socket.close(); //发送文件主体 byte [] buffer = new byte [ 1024 ]; int blocknum=filelen/buffer.length; //将文件分成1024个字节的block,blocknum是块的个数,即循环次数 int lastsize=filelen%buffer.length; //最后一个packet的字节数 //socket=new DatagramSocket(); for ( int i= 0 ;i<blocknum;i++){ fis.read(buffer, 0 , buffer.length); //从文件流读入buf中 packet= new DatagramPacket(buffer,buffer.length,server_ip,UDPClient. this .server_port+ 2 ); socket.send(packet); System.out.println( new String(packet.getData())); Thread.sleep( 1 ); //简单的防止丢包 } //发送最后一个block的内容 fis.read(buffer, 0 , lastsize); packet= new DatagramPacket(buffer,buffer.length,server_ip,UDPClient. this .server_port+ 2 ); socket.send(packet); System.out.println( new String(packet.getData())); Thread.sleep( 1 ); //关闭fis和socket fis.close(); socket.close(); UDPClient. this .label_file_state.setText( "文件当前状态:文件传输完毕。" ); UDPClient. this .label_file_state.setText( "文件当前状态::无任务" ); } catch (Exception e1){ System.out.println(e1); } } catch (Exception ex){ JOptionPane.showMessageDialog(UDPClient. this , "打开文档出错!" ); } } } }); try { //获得本机ip , 目标ip this .client_ip=InetAddress.getLocalHost(); this .server_ip=InetAddress.getByName(ip); label_client_ip.setText( "本机ip:" + this .client_ip.getHostAddress()); //显示在面板上 label_server_ip.setText( "目标ip:" + this .server_ip.getHostAddress()); //显示在面板上 System.out.println( this .server_ip.getHostAddress()); } catch (Exception ex){ System.out.println(ex); } } /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater( new Runnable() { public void run() { try { UDPClient client = new UDPClient( "UDPClient" , "127.0.0.1" , 6000 , 10000 ); client.setVisible( true ); } catch (Exception e) { e.printStackTrace(); } } }); } } |
MyServer端源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | import java.awt.Color; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketAddress; import java.sql.Date; import java.text.SimpleDateFormat; import java.util.Timer; import java.util.TimerTask; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.WindowConstants; import java.awt.*; import javax.swing.*; import java.awt.event.*; public class MyServer extends JFrame { // 添加属性 private JPanel panel = new JPanel(); private JButton button_receive = new JButton( "另存为" ); private JLabel label_fileState = new JLabel( "当前状态:无任务" , JLabel.CENTER); private JLabel label_cip= new JLabel( "本 机ip:" ,JLabel.CENTER); private JLabel label_sip= new JLabel( "服务器ip:" ,JLabel.CENTER); private JLabel label_cport = new JLabel( "本机端口:10000" ,JLabel.CENTER); private JLabel label_sport = new JLabel( "目标端口:6000" ,JLabel.CENTER); private InetAddress cip = null ; //本机ip private InetAddress sip = null ; //对方ip private int otherport; private int myport; DatagramSocket socket; // 接收文件来显提示 DatagramSocket socket1; // 接收文件信息 DatagramSocket socket2; // 接收平时的聊天信息 // String filename = null ; byte buffer[] = new byte [ 1024 ]; int fileLen = 0 ; int numofBlock = 0 ; int lastSize = 0 ; // String str_name; // public MyServer(String str_name, String str_ip, int otherport, int myport) { super (str_name); this .str_name = str_name; this .setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); this .setBounds( 600 , 250 , 400 , 500 ); // 添加功能代码 this .setLayout( new GridLayout( 6 , 1 , 7 , 7 )); button_receive.setFont( new Font( "楷体" , 1 , 20 )); button_receive.setBackground(Color.LIGHT_GRAY); Font font = new Font( "楷体" ,Font.PLAIN, 20 ); label_cip.setFont(font); label_sip.setFont(font); label_cport.setFont(font); label_sport.setFont(font); label_fileState.setFont(font); //this.add(panel); this .add(label_cip); this .add(label_sip); this .add(label_cport); this .add(label_sport); this .add(button_receive); this .add(label_fileState); this .setVisible( true ); // this .otherport = otherport; this .myport = myport; // button_receive.addActionListener( new ActionListener() { // 吧file1另存为file2 public void actionPerformed(ActionEvent e) { // 选择要接收的文件 JFileChooser filechooser = new JFileChooser(); int result = filechooser.showSaveDialog(MyServer. this ); if (result == JFileChooser.APPROVE_OPTION) { try { File file2 = filechooser.getSelectedFile(); System.out.println( "选择文件\n" ); try { File file1 = new File( "D:\\TT\\" + filename); System.out.println(filename+ "选择文件\n" ); saveAs(file1, file2); System.out.println( "sava文件\n" ); } catch (Exception ex) { System.out.println(ex); } } catch (Exception ex) { JOptionPane.showMessageDialog(MyServer. this , "打开保存出错!" ); } } } }); try { this .cip=InetAddress.getLocalHost(); this .sip = InetAddress.getByName(str_ip); label_cip.setText( "本机ip:" + this .cip.getHostAddress()); //显示在面板上 label_sip.setText( "目标ip:" + this .sip.getHostAddress()); //显示在面板上 System.out.println( this .sip.getHostAddress()); socket = new DatagramSocket( this .myport); socket1 = new DatagramSocket( this .myport + 1 ); socket2 = new DatagramSocket( this .myport + 2 ); System.out.println( "等待接受文件..." ); while ( true ){ //接收文件名称 byte filetipBuf[] = new byte [ 256 ]; // 防止文件名字过长(此处最长256个字符) DatagramPacket packet_tip = new DatagramPacket(filetipBuf, 0 , filetipBuf.length); socket.receive(packet_tip); System.out.println( new String(packet_tip.getData())); String str_filetip = new String(packet_tip.getData(), 0 ,packet_tip.getLength()); filename = str_filetip.substring( 8 ); //接收文件长度(字节数) byte [] fileLenBuf = new byte [ 12 ]; // 可以传输1T的文件 DatagramPacket packet_len = new DatagramPacket(fileLenBuf,fileLenBuf.length); socket1.receive(packet_len); System.out.println( new String(packet_len.getData())); String str_fileLen = new String(fileLenBuf, 0 ,packet_len.getLength()); fileLen = Integer.parseInt(str_fileLen); label_fileState.setText( "当前状态:正在接收!" ); //接收文件内容 DatagramPacket packet_file = new DatagramPacket(buffer, 0 ,buffer.length); numofBlock = fileLen / buffer.length; // 循环次数(将该文件分成了多少块) lastSize = fileLen % buffer.length; // 最后一点点零头的字节数 File file = new File( "D:\\TT\\" + filename); FileOutputStream fos = new FileOutputStream(file); // 从内存取出存入文件 for ( int i = 0 ; i < numofBlock; i++) { packet_file = new DatagramPacket(buffer, 0 ,buffer.length); socket2.receive(packet_file); // 通过套接字接收数据 System.out.println( new String(packet_file.getData())); fos.write(buffer, 0 , 1024 ); // 写入文件 } // 接收最后一点点零头 packet_file = new DatagramPacket(buffer, 0 , lastSize); socket2.receive(packet_file); // 通过套接字接收数据 System.out.println( new String(packet_file.getData())); fos.write(buffer, 0 , lastSize); // 写入文件 fos.close(); // 反馈包 label_fileState.setText( "文件接收完毕!" ); label_fileState.setText( "当前状态:无任务" ); // socket.close(); // socket1.close(); // socket2.close(); } } catch (Exception ex) { System.out.println( "1" ); } } public void saveAs(File file1, File file2) { // 把file1另存为file2,并删掉file1 try { FileInputStream fis = new FileInputStream(file1); FileOutputStream fos = new FileOutputStream(file2); byte buf[] = new byte [ 1024 ]; int len = 0 ; while ((len = fis.read(buf)) != - 1 ) { fos.write(buf, 0 , len); } fis.close(); fos.close(); //file1.delete(); } catch (Exception ex) { System.out.println(ex); } } /////////////////////////////////////////////// public static void main(String args[]) { new MyServer( "Server" , "127.0.0.1" , 6000 , 10000 ); } } |
本机环回地址测试通过,如有问题,请指正。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通