基于UDP实现手机和电脑PC端消息通信
一.首先要先了解一下UDP套接字的网络通信
TCP和UDP都是传输层的两个协议,最近在学习安卓,想要实现手机和电脑的通信,TCP虽然安全性能好,但是实现起来比较麻烦,在自己想要初步实现一个简易的通信,可以从UDP先实现,两者去区别会在后面完善,这里就先以UDP为主。
我们先来看一下UDP的包头
从上图可以看到,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();
}
}
});
}
}