上篇博客中,面向UDP的Android——PC双向通信(一):实现Android客户端和PC服务器端的单向通信,我们介绍了如何实现Android客户端向Java服务器端发送消息,这次我们尝试实现两者之间的双向通信。
我们需要实现的是,对于Android客户端,增加接收信息的方法,对于Java服务器端,增加发送消息的方法。
我们需要增加的是接收消息的方法,接收到消息后,将消息显示在页面上。
接收消息的代码与上篇博客Java服务器端接收消息的代码类似:
public DatagramSocket socket;
public void receiveMsg(){
try{
//创建socket对象
socket = new DatagramSocket(9999);
while(true){
byte data[] = new byte[1000];
//创建数据报包
DatagramPacket request = new DatagramPacket(data,data.length);
//接收数据报包
socket.receive(request);
String s = new String(data,"GBK");
/*将数据显示在页面上*/
......
}
} catch(Exception e){
e.printStackTrace();
}
}
由于接收消息是在子线程中进行的,但组件只能在主线程中进行修改,所以需要用到Android特有的消息处理机制handler机制。
先创建Handler对象,重写handleMessage(Message msg)方法:
private Handler handler = new Handler(){
public void handlerMessage(Message msg){
String s = (String) msg.obj;
TextReceive.setText(s);
}
}
再在接收消息的方法中增加发送消息到主线程消息队列的代码即可:
Message message = handler.obtainMessage();
message.obj = s;
handler.sendMessage(message);
Java服务器端需要增加发送消息的代码,和Android客户端增加消息的代码类似。
/**
* 发送消息
* @throws Exception
*/
public void sendMsg() throws Exception{
System.out.println("准备发送消息");
String Msg = MsgSend.getText();
System.out.println("要发送的消息是: "+Msg);
byte data[] = Msg.getBytes("GBK");
DatagramPacket request =
new DatagramPacket(data,data.length,ClientAddress,9999);
socket.send(request);
System.out.println("发送成功");
}
package com.myscelyn.udpclient;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class MainActivity extends AppCompatActivity {
public DatagramSocket socket;
public EditText TextSend;
public TextView TextReceive;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button BtnSend = this.findViewById(R.id.BtnSend);
TextSend = this.findViewById(R.id.TextSend);
TextReceive = this.findViewById(R.id.TextReceive);
try{
socket = new DatagramSocket(9999);
}catch(Exception e){
e.printStackTrace();
}
BtnSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String msg = TextSend.getText().toString();
new Thread(){
public void run(){
sendMsg(msg);
}
}.start();
}
});
new Thread(){
public void run(){
receiveMsg();
}
}.start();
}
public void receiveMsg(){
try{
while(true){
byte data[] = new byte[1000];
DatagramPacket request = new DatagramPacket(data,data.length);
socket.receive(request);
String s = new String(data,"GBK");
Message message=handler.obtainMessage();
message.obj=s;
handler.sendMessage(message);
}
} catch(Exception e){
e.printStackTrace();
}
}
private Handler handler=new Handler(){
public void handleMessage(Message msg)
{
String s=(String)msg.obj;
TextReceive.setText(s);
}
};
public void sendMsg(String msg){
Log.v("Client send:",msg);
Toast.makeText(MainActivity.this,msg,Toast.LENGTH_LONG);
try{
byte data[] = msg.getBytes("GBK");
InetAddress ServerAddress = InetAddress.getByName("192.168.31.233");
DatagramPacket request =
new DatagramPacket(data,data.length,ServerAddress,9999);
socket.send(request);
}
catch(Exception e){
e.printStackTrace();
}
}
}
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
public class UDPServer {
public JFrame frame;
public JLabel IPShow;
public JLabel PortShow;
public JTextArea MsgReceive;
public JTextArea MsgSend;
public JButton SendBtn;
public InetAddress ClientAddress;
public String AddressStr;
public int ClientPort;
public DatagramSocket socket;
public static void main(String[] args) throws Exception{
UDPServer server = new UDPServer();
server.showUI();
server.receiveMsg();
}
public void showUI(){
frame = new JFrame("UDP Server");
frame.setSize(800, 700);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
JLabel IPLabel = new JLabel(" 源IP:");
IPLabel.setPreferredSize(new Dimension(80,30));
IPShow = new JLabel("__________________");
IPShow.setPreferredSize(new Dimension(300,30));
JLabel PortLabel = new JLabel("端口:");
PortLabel.setPreferredSize(new Dimension(80,30));
PortShow = new JLabel("__________________");
PortShow.setPreferredSize(new Dimension(300,30));
JLabel RecvLabel = new JLabel("接收到消息:");
RecvLabel.setPreferredSize(new Dimension(700,30));
MsgReceive = new JTextArea();
MsgReceive.setPreferredSize(new Dimension(750,200));
JLabel SendLabel = new JLabel("待发送消息:");
RecvLabel.setPreferredSize(new Dimension(700,30));
MsgSend = new JTextArea();
MsgSend.setPreferredSize(new Dimension(750,200));
SendBtn = new JButton("发送");
SendBtn.setPreferredSize(new Dimension(80,60));
SendBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
sendMsg(); //发送消息
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
frame.add(IPLabel); //源IP
frame.add(IPShow);
frame.add(PortLabel); //端口
frame.add(PortShow);
frame.add(RecvLabel); //接收到消息:
frame.add(MsgReceive);
frame.add(SendLabel); //待发送消息:
frame.add(MsgSend);
frame.add(SendBtn); //发送按钮
frame.setVisible(true);
}
/**
* 接收消息
* @throws Exception
*/
public void receiveMsg() throws Exception{
System.out.println("UDPServer start...");
socket = new DatagramSocket(9999);
new Thread(){
public void run(){
while(true){
byte[] data = new byte[52];
DatagramPacket request = new DatagramPacket(data, 52);
System.out.println("准备接收消息");
try {
socket.receive(request);
System.out.println("消息接收完毕");
ClientAddress=request.getAddress();
IPShow.setText(ClientAddress.toString());
System.out.println("客户机IP地址:"+IPShow.getText());
ClientPort=request.getPort();
PortShow.setText(""+ClientPort);
System.out.println("客户机端口:"+PortShow.getText());
String s = new String(data,"GBK");
System.out.println("收到新消息:"+s+"\n"+s.length());
MsgReceive.setText(s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
}
/**
* 发送消息
* @throws Exception
*/
public void sendMsg() throws Exception{
System.out.println("准备发送消息");
String Msg = MsgSend.getText();
System.out.println("要发送的消息是: "+Msg);
byte data[] = Msg.getBytes("GBK");
DatagramPacket request =
new DatagramPacket(data,data.length,ClientAddress,9999);
socket.send(request);
System.out.println("发送成功");
}
}
本来放假了想偷懒,但是时间一久,有些细节果然记得不清晰了,还是得及时记录呀!
接下来打算制定协议,在现有的基础下传输一个自定义类的对象。留着第三篇来写吧!
面向UDP的Android——PC双向通信(三):在Android客户端和PC服务器端之间传输自定义对象