通过UDP通信,实现Android设备与PC端的双向通信

首先展示Android设备和PC端的界面:

通过UDP通信,实现Android设备与PC端的双向通信

 

通过UDP通信,实现Android设备与PC端的双向通信

 

步骤:

首先,PC端按下“接收”按钮,使PC端进入接收状态;

此时,Android端输入框输入数据后,按下“发送”,可以将输入框上的数据发送到PC端。

接着,在PC端上方的发送框输入数据,按下发送,可以将数据发送到Android端,数据显示在LogCat日志上。

 

有关发送的原理,我在我的上一篇博客里已经简单说明啦,所以在此不做介绍,把代码拿出来,说明几个需要注意的地方。

上一篇链接:怎样实现UDP通信,使Android设备上的数据成功发送到PC机上?

Android端代码如下:



public class SendActivity extends Activity {

	DatagramSocket Socket;
	int DuanKouShou = 3013;        //用来接收数据的端口,假设端口号为3013
	int DuanKouFa = 4013;            //用来发送的端口,假设端口号为4013
/*
值得注意的是:要想把数据发送和接收无误,
    Android端用于接收的端口,与PC端用于发送的端口,端口号要一致 ;
    Android端用于发送的端口,与PC端用于接收的端口,端口号要一致。 
*/

	Thread TSend;  //发送线程,相当于建立一个Android端用于发送数据的平台
	Thread threadRece;	//接收线程,同上
	
	

	
    @Override
    //发送方是“手机”
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_send);
        
        Button Bt1 = (Button)this.findViewById(R.id.bt1);
        Button Bt2 = (Button)this.findViewById(R.id.bt2);
        final EditText et = (EditText)this.findViewById(R.id.eT1);
        //创建好界面图标,并与程序连接
        Bt1.setOnClickListener(new OnClickListener(){
			
			//当按下按钮时,执行以下方法
			public void onClick(View v) {
				// TODO Auto-generated method stub
			 TSend = new Thread(){
					
					public void run(){
						

						String str = et.getText().toString();//获取输入框的信息

						Log.v("fist","可以发送:"+ str);
						SendMsg(str);   //只要一按按钮,就发送数据
						if(Socket!=null)
							Socket.close();
				}
				};
				TSend.start();
				Log.v("fist","线程执行完啦!");
			}
        });          
        

        
        Bt2.setOnClickListener(new OnClickListener(){

			//当按下“接收”按钮后,开始执行接收操作
			
			public void onClick(View v) {
							
				new Thread(){
					public void run(){
				
						try {	
            //接收方法在此调用哟
							receiveMsg();							
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							Log.v("fist","是手机接受异常!" + e);
							
						}
					}
				}.start();
				
			}
    });
    }
   


    private void receiveMsg() throws Exception{
        //Android端的接收方法

		Log.v("fist", "手机数据接收开始");
		//Toast.makeText(this, "登录成功", Toast.LENGTH_LONG).show();
		
		try {

			Socket = new DatagramSocket(DuanKouFa);

			byte[]  data=new byte[1024];

			DatagramPacket pack = new DatagramPacket(data, data.length);

			Socket.receive(pack);			//关键问题: 在这里卡住了!收不到消息

			int len = pack.getLength();

			
			byte[] tong = new byte[len];
			for(int i = 0 ; i < len ; i++ )
				tong[i] = data[i];	
			
			String str=new String(tong);
//			
			Log.v("fist", "接收成功,消息为: "  + str );
//			Socket.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.v("fist", " 接收异常 ,异常为 :   "  + e +"\n"+e.getLocalizedMessage());
//			Toast.makeText(this, "接收异常" + e, Toast.LENGTH_LONG).show();
		}
    } 
        
    
    
	    private void SendMsg(String msg){
	    	//Android端的发送方法

	    	Log.v("fist", "开始发送!");
	    	try {
	    		
	    		Socket = new DatagramSocket(DuanKouFa);
				InetAddress serverAddress = InetAddress.getByName("192.168.43.84");
				byte data[] = msg.getBytes();//把要发送的数据转化为Byte形式
				
				DatagramPacket package1 = new DatagramPacket(data,data.length,
						serverAddress,DuanKouShou);//设置一个发送包(相当于快递,写了快递的地址和编号)
				
				Socket.send(package1);//发送快递
				Log.v("fist", "发送成功!");

			} catch (Exception e) {
				// TODO Auto-generated catch block
				Log.v("fist", "发送异常"+ e);
				e.printStackTrace();
			}
	    }
    

    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.send, menu);
        return true;
    }
        
        }
    
    

 

PC端代码:

public class UDPServer extends JFrame{

	DatagramSocket socket ;  //这个类的快递员
	final int DuanKouFa = 4013; //这个站点的“发送”端口
	final int DuanKouShou = 3013;  //这个站点用来接收的端口;
	
	
	public void init(){
		this.setTitle("发送接受器");
		this.setSize(400,400);
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		
		FlowLayout fl = new FlowLayout();
		this.setLayout(fl);
		
		final JTextField Tx = new JTextField();
		Tx.setPreferredSize(new Dimension(300,50));
		this.add(Tx);
		
		JButton bt1 = new JButton("发送");
		this.add(bt1);
		
		bt1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				String name = e.getActionCommand();
				System.out.println("输出信息:" + name);
				new Thread()//当下这个线程已经没问题了
					{
					public void run(){
						
						String str = Tx.getText();
						SendMsg(str);
						System.out.println("数据发送成功:  " + str);
										
					}
					}.start();
					if(socket!=null)
					socket.close();
					System.out.println("端口关闭? " + socket.isClosed());//这里也可以执行到
			}
		});
		
		final JTextField Tx2 = new JTextField();
		Tx2.setPreferredSize(new Dimension(300,50));
		this.add(Tx2);
		
		JButton bt2 = new JButton("接收");
		this.add(bt2);
		
		bt2.addActionListener(new ActionListener(){

			public void actionPerformed(ActionEvent arg0) {
				String name = arg0.getActionCommand();
				System.out.println("输出信息:" + name);
				names = "接收";
				new Thread()
				{
				public void run(){
					try {
						
							receiveMsg();
							if(socket != null)
								socket.close();
						
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						System.out.println("接收异常: "  + e);
					}
					}				
				}.start();
				
			}				
		});
		this.setVisible(true);
	}
	
	
	private int Ip;
	private InetAddress Ipt;
	private String names = "";
	private String St = "";
	private void SendMsg(String msg){
    	System.out.println(" ");
    	System.out.println("电脑开始发送!");
    	try {
    		
    			socket = new DatagramSocket(DuanKouFa);
				
				byte data[] = msg.getBytes();//把要发送的数据转化为Byte形式
			
				DatagramPacket package1 = new DatagramPacket(data,data.length,
						Ipt,Ip);//设置一个发送包(相当于快递,写了快递的地址和编号)
				System.out.println("发送端口号为: "  + Ip);
				System.out.println("发送Ip地址为: "  + Ipt);
				socket.send(package1);//发送快递
			
				System.out.println("发送成功!");
				
				
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("发送异常,异常为:  " + e);
			e.printStackTrace();
		}//设置端口号,
    }
	
	
	private void receiveMsg() throws Exception{
		System.out.println("数据接受开始!!!!"  );
		
		try {
			socket = new DatagramSocket(DuanKouShou);
			byte[]  data=new byte[1024];
			DatagramPacket pack = new DatagramPacket(data, data.length);
			socket.receive(pack);			
			int len = pack.getLength();
			
			byte[] tong = new byte[len];
			for(int i = 0 ; i < len ; i++ )
				tong[i] = data[i];	
			Ip = pack.getPort();
			Ipt = pack.getAddress();
			System.out.println("获取的端口号为:" +Ip );
			System.out.println("获取的IP地址为:" +Ipt );
			
			String str=new String(tong);
			
			System.out.println("收到信息: "+ str);

		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("接收异常!  "+ e);
		} 			
	}
		
	
	public static void main(String[] args)throws Exception {
		
		UDPServer UDps = new UDPServer();
		
		UDps.init();		
	
		}

几个值得注意的地方:

1、要想成功发送和接收数据,Android端用于发送的端口与PC端用于接收的端口,端口号要一致;Android端用于接收的端口与PC端用于发送的端口,端口号要一致;

2、满足上条后,还要满足:Android端用于发送的IP地址与PC端用于接收的IP地址一致;Android端用于接收的IP地址与PC端用于发送的IP地址一致;

3、由于Android端发送数据所用的IP地址与端口号事先不明,因此,在PC端设置2个变量: 

    private int Ip;      
    private InetAddress Ipt; 

先从Android端获取数据,获取数据的同时,用变量Ip获取Android端发送的端口号;用变量Ipt获取Android端发送用的IP地址。

此时,从PC端发送数据到Android端。