基于UDP实现手机和电脑PC端消息通信

一.首先要先了解一下UDP套接字的网络通信
TCP和UDP都是传输层的两个协议,最近在学习安卓,想要实现手机和电脑的通信,TCP虽然安全性能好,但是实现起来比较麻烦,在自己想要初步实现一个简易的通信,可以从UDP先实现,两者去区别会在后面完善,这里就先以UDP为主。
我们先来看一下UDP的包头
基于UDP实现手机和电脑PC端消息通信
从上图可以看到,UDP包头结构简单,是需要知道源端口号和目标端口号,看起来就是很天真,总结起来有以下几个优特点:

1.沟通简单,不需要复杂的数据结构
2.UDP很容易轻信他人,不需要建立连接再发送消息,它可以监听一个端口号,可以随意给任何人发消息,任何人也可以给它发消息
3.有点目中无人,不管消息包是否丢失,就是会一直发消息,不会进行消息堵塞的控制

二.下面我们来具体实现一下手机和PC的通信
实现的方法分为两方面:发送和接受方法:这里可以和实际生活联系起来,我们收发快递,需要快递员在乙方取快递,填写好地址打包,发送,需要另一个快递员按照地址给甲方送快递,那就按照这个思路理解下面的方法喽!
发送:方法思路如下

1.创建一个套接字DatagramSocket对象,指定要发送消息的端口号(是发送和接收的桥梁,两者通过一致的一对端口号进行通信);
2.需要一个byte数组将要发送的字符串转换为字节存储在这里;
3.将上面的字节数组打包,需要一个DatagramPacket
4.通过套接字对象将数据包发送

接收:方法思路如下——和上面对应
1.同样创建一个套接字DatagramSocket对象,指定和发送端同样的端口号;
2.给定一个足够大小的byte字节数组,用来存储接收到的数据
3.创建一个byte字节数组大小的包,用来接收
4.通过套接字对象接收数据包
5.将接受到的数据包转换为字符串显示

下面看具体手机端接收和发送实现
说明几点:
·发送消息是绑定在手机端发送按钮上的方法 ,需要一个开启线程来发送消息 ;
·接收方法也是绑定在一个手机端开启按钮上,同样需要一个线程来接收;

public class MainActivity extends Activity {

	public Button senBtn = null;
	public EditText sendMsg = null;
	public TextView fromMsg = null;
	public Button startBtn = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		Log.v("tag", "create!aaaaaaaaaaa");
		setContentView(R.layout.activity_main);
		fromMsg = (TextView) this.findViewById(R.id.from_msg);
		sendMsg = (EditText) this.findViewById(R.id.to_msg);
		senBtn = (Button) this.findViewById(R.id.send_btn);
		startBtn = (Button) this.findViewById(R.id.start_btn);
		Log.v("tag", "打印");
		// 手机端接收
		startBtn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				startBtn.setText("已开启");
				runReceive();
			}
		});
        //手机端发送
		senBtn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				android_Client();
			}
		});
	}
    //接收方法
	private void runReceive() {
		// TODO Auto-generated method stub
		new Thread(new Runnable() {
			public void run() {
				DatagramSocket socket = null;
				try {
					socket = new DatagramSocket(8888);
					while (true) {
						byte data[] = new byte[1024];
						DatagramPacket packet = new DatagramPacket(data,
								data.length);
						
							try {
								socket.receive(packet);
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						
						final String result = new String(packet.getData(),
								packet.getOffset(), packet.getLength());
						Log.i("收到消息:", result);
						runOnUiThread(new Runnable() {
							public void run() {
								Log.i("设置消息", result);
								fromMsg.setText(fromMsg.getText().toString()
										+ "\n" + result);
								Log.i("手机显示:", result);
							}
						});
					}
				} catch (SocketException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}).start();
	}
   //发送方法
	protected void android_Client() {
		// TODO Auto-generated method stub
		new Thread(new Runnable() {
			public void run() {
				DatagramSocket client = null;
				try {
					client = new DatagramSocket(9990);
					while (true) {
						String str = "Phone:"
								+ sendMsg.getText().toString().trim();
						// 获取输入的文本信息内容
						byte[] data = str.getBytes("utf_8");
						DatagramPacket dp = new DatagramPacket(data,
								data.length,
								InetAddress.getByName("192.168.31.5"), 9990);
						client.send(dp);
						final String result = new String(dp.getData(),
								dp.getOffset(), dp.getLength());
						Log.i("发送的消息为:", result);
						client.close();
					}
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}).start();
	}

PC端发送和接收的实现

public class ServerClass{
	public static  JFrame jf;
	public static  JButton jbu;
	public static  JTextArea text1;
	public static  JTextArea text2;
	public static  JLabel recLable;
	public static void main(String[] args) throws Exception {
		ServerClass server=new ServerClass();
		server.showUI();
		//不断调用PC端接收信息的函数
		while(true){
			receive();
		}
	}
	//PC端接收方法
	public static void receive() throws SocketException {
		// TODO Auto-generated method stub
		while(true){
			DatagramSocket server=new DatagramSocket(9990);
			byte []data=new byte[1024];
			DatagramPacket packet=new DatagramPacket(data, data.length);
			try {
				server.receive(packet);
				final String result = new String(packet.getData(), packet.getOffset(), packet.getLength());
	    		text1.setText(result);
                System.out.println("接收到的消息为:"+result.toString());
                server.close();

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	//PC端发送消息
	 public static void sendMsg() throws IOException{
    	 System.out.println("开始发送");
    	 DatagramSocket ds=new DatagramSocket(8888);
    	 String str="Pc端说:"+text2.getText().toString().trim();
    	 System.out.println("PC端发送的内容为"+str);
    	 byte[] buf=str.getBytes("utf-8");
    	 DatagramPacket dp=new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.31.126"), 8888);
    	 ds.send(dp);
    	 ds.close();
     }
	 //PC端显示界面方法
	public void showUI() {
		// TODO Auto-generated method stub
		jf=new JFrame("UDP");
		jf.setSize(600,600);
	    jf.setLocationRelativeTo(null);
	    jf.setDefaultCloseOperation(0);
	    jf.setLayout(new FlowLayout());
	    text1=new JTextArea();
	    text1.setPreferredSize(new Dimension(500,200));
	    recLable=new JLabel();
	    recLable.setPreferredSize(new Dimension(100,30));
	    recLable.setText("接收到的消息");
	    text2=new JTextArea();
	    text2.setPreferredSize(new Dimension(500,200));
	    jbu= new JButton("发送");
	    jbu.setPreferredSize(new Dimension(100,30));
	    jf.add(text1);
	    jf.add(recLable);
	    jf.add(text2);
	    jf.add(jbu);
	    jf.setVisible(true);
	    jbu.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent v) {
				// TODO Auto-generated method stub
				try {
					sendMsg();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
	}
}