UDP通信(PC作为Server,安卓手机作为Client)

该博客介绍了使用UDP协议进行手机与PC间实时通信的延时测试。通过Java和C++实现的服务器端代码展示了UDP无连接、低开销的特点。Android端的Java代码展示了发送消息的过程,测试结果显示延时在100ms内,满足实时性需求。
摘要由CSDN通过智能技术生成

UDP

用户数据报协议(UDP,User Datagram Protocol)是一种无需建立连接就可以发送封装的 IP 数据包的方法。

特点:

 (1)无连接

 (2)开销小

 (3)可多对多

连接方式:无连接,只负责发送

与TCP相比:

优点:

 (1)传输效率高

 (2)可一对多

缺点:

  (1)不可靠

本次项目目标:采用UDP通信,测试手机与PC实时显示的延时。

PC(Java)Server端代码:

public class UDPServer implements Runnable {
	private static final int PORT = 6000;
	private byte[] msg = new byte[1024];
	private boolean life = true;
	public UDPServer() {
	}
 
	public boolean isLife() {
		return life;
	}
 
	public void setLife(boolean life) {
		this.life = life;
	}
 
	@Override
	public void run() {
		DatagramSocket dSocket = null;
		DatagramPacket dPacket = new DatagramPacket(msg, msg.length);
		try {
			dSocket = new DatagramSocket(PORT);
			while (life) {
				try {
					dSocket.receive(dPacket);
					Log.i("msg sever received", new String(dPacket.getData()));
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} catch (SocketException e) {
			e.printStackTrace();
		}
	}
}

 

PC(C++)Server端代码:

#include <iostream>
#include <winsock2.h>
#include <stdio.h>
#include <sys/timeb.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")//连接库
#include <ctime>
#include <string>
#include <sstream>
#include <iomanip>


int main()
{//创建套接字,相当于句柄
	WORD Version;
	WSADATA wData;
	Version = MAKEWORD(2, 2);
	int n = WSAStartup(Version, &wData);
	if (n != 0)//检查是否出错,不过一般不会出错的
	{
		cout << "Error!" << endl;
		return -1;
	}
	SOCKET soc = socket(AF_INET, SOCK_DGRAM, 0);
	if (INVALID_SOCKET == soc)
	{
		cout << "Error!" << endl;
		return -1;
	}
	//创建端口
	sockaddr_in addSer;
	addSer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addSer.sin_family = AF_INET;
	addSer.sin_port = htons(6666);   //端口随便,端口号的有效范围是从0到65535。
	n = bind(soc, (sockaddr*)&addSer, sizeof(addSer));   //一般来说,大于49151的端口号都代表动态端口。绑定套接字
	if (n == SOCKET_ERROR)    //出错检查,出错,可能端口被占用了,需要换一个
	{
		cout << "Error!" << endl;
		return -1;
	}
	char Send[256];        //发送字符串
	char Rev[256];         //接收字符串
	long Time1;
	long Time2;
	sockaddr_in addClient;  //接收方的地址信息结构体
	int len = sizeof(sockaddr);
	struct timeb t;
	while (1)
	{
		int i = recvfrom(soc, Rev, 256, 0, (sockaddr*)&addClient, &len); //接受,阻塞在这,直到接收到信息
		Rev[i] = '\0';
		if (Rev[0] == 'Q')
		{
			cout << "Char end!" << endl;
			break;
		}
		cout << inet_ntoa(addClient.sin_addr) << " say :" << Rev << endl;  //输出发送方的IP,和信息

		ftime(&t);
		Time1 = t.time;
		Time2 = t.millitm;
		cout << Time1 << "." << Time2 << endl;
		//sendto(soc, Time, strlen(Time), 0, (sockaddr *)&addClient, len);    //发送消息
	}
	closesocket(soc);      //关闭套接字
	WSACleanup();
	return 0;
}

Android端(Java)代码:

    AndroidManifest.xml中增加权限:

<uses-permission android:name="android.permission.INTERNET" />

    mainactivity主程序代码:

package com.example.udp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        et = (EditText) findViewById(R.id.input);
        btn = (Button) findViewById(R.id.btn_send);

        System.out.println("启动");
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(sendMyMessage).start();//新线程,防止堵塞主线程
            }
        });
    }

    private DatagramSocket socket;
    private DatagramPacket packet;
    private final String IP = "192.168.43.107";
    private final int ServerPORT = 6666;
    private final int ClientPORT = 6666;
    private EditText et;
    private Button btn;
    String Time;

    Runnable sendMyMessage = new Runnable() {
        @Override
        public void run() {
            try {
                socket = new DatagramSocket(ClientPORT);//本地发送窗口
                //InetAddress serverIP=InetAddress.getByName(IP);
                Time = Long.toString(System.currentTimeMillis());

                packet = new DatagramPacket(Time.getBytes(), Time.getBytes().length, InetAddress.getByName(IP), ServerPORT);//数据打包,服务器地址和接收窗口
                socket.send(packet);//发送消息
                /*接受服务器回传消息
                packet = new DatagramPacket(buf,buf.length);
                socket.receive(packet);*/
                socket.close();//发送完就可以关闭了,防止端口占用
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
}

   Layout代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:hint="请输入发送的信息"
        android:id="@+id/input"
        />


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:id="@+id/btn_send"
        android:layout_marginTop="10dp"
        android:text="send"/>


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/receive"
        android:text="收到信息为: "
        />
</LinearLayout>

多次测试延时在100ms内,低延时,符合实时性,后续将基于udp探索实时传输视频的通信方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值