Android开发菜鸟级入门4--网络编程之套接字UDP

由于项目需要,现在小白开始安卓网络编程的学习
安卓的网络编程分为
基于socket
基于http
首先来学基于socket的
socket通信有两种协议UDP和TCP
UDP不需要连接但不保证发送成功率速度快,TCP需要连接保证发送成功率速度相对慢

首先先使用UDP
因为项目需要安卓手机与计算机通信所以,我把服务端装在计算机上
首先,我测试了PC机上的UDP通信

PC服务器端:
#include<stdio.h>
#include<winsock2.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;

#pragma comment(lib,"ws2_32.lib")

#define PORT 4567
#define ADDR "192.168.137.1"

int main()
{
	WSADATA wsock;
	SOCKET sersocket;
	SOCKADDR_IN serAddr;
	int serAddrsize = sizeof(serAddr);
	int nRet = 0;
	char buf[1024];
	printf("Initialising Winsock...\n");
	if (WSAStartup(MAKEWORD(2, 2), &wsock) != 0)
	{
		exit(0);
	}
	printf("Initialised successfully!\n");
	printf("Creating UDP Socket...\n");
	if ((sersocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
	{
		WSACleanup();
		return 0;
	}
	printf("UDP Socket Created successfully!\n");
	serAddr.sin_family = AF_INET;
	serAddr.sin_port = htons(PORT);
	serAddr.sin_addr.S_un.S_addr = inet_addr(ADDR);
	if (bind(sersocket, (SOCKADDR*)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
	{
		closesocket(sersocket);
		WSACleanup();
		return 0;
	}
	printf("Waiting for receive data...\n");
	for (int i = 0;;i++)
	{
		memset(buf, 0, sizeof(buf));
		if ((nRet = recvfrom(sersocket, buf, sizeof(buf), 0, (SOCKADDR*)&serAddr, &serAddrsize)) == SOCKET_ERROR)
		{
			closesocket(sersocket);
			WSACleanup();
			return 0;
		}
		cout << nRet << endl;
		puts(buf);
		cout << strlen(buf) << endl;
		if ((nRet = sendto(sersocket, buf, strlen(buf), 0, (SOCKADDR*)&serAddr, sizeof(serAddr))) == SOCKET_ERROR)
		{
			closesocket(sersocket);
			WSACleanup();
			return 0;
		}
		if (strcmp(buf, "exit") == 0)
		{
			printf("exit the receiving loop\n");
			break;
		}
	}
	closesocket(sersocket);
	WSACleanup();
	return 0;
}

PC客户端
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<winsock2.h>
#include<cstdio>
using namespace std;
#pragma comment(lib, "ws2_32.lib")

#define PORT 4567
#define ADDR "192.168.137.1"

int main()
{
	WSADATA wsock;
	SOCKET clisocket;
	SOCKADDR_IN serAddr;
	int serAddrsize = sizeof(serAddr);
	int nRet = 0;
	char buf[1024];
	printf("Initialsing Winsock...\n");
	if (WSAStartup(MAKEWORD(2, 2), &wsock) != 0)
	{
		exit(0);
	}
	printf("Initialised successfully!\n");
	printf("Creating UDP Socket...\n");
	if ((clisocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
	{
		WSACleanup();
		return 0;
	}
	serAddr.sin_family = AF_INET;
	serAddr.sin_port = htons(PORT);
	serAddr.sin_addr.S_un.S_addr = inet_addr(ADDR);
	printf("UDP Socket Created successfully!\n");
	printf("Trying to send messages\n");
	for (int i = 0;;i++)
	{
		memset(buf, 0, sizeof(buf));
		printf("Message to sent:\n");
		cin >> buf;
		if ((nRet = sendto(clisocket, buf, strlen(buf), 0, (SOCKADDR*)&serAddr, sizeof(serAddr))) == SOCKET_ERROR)
		{
			closesocket(clisocket);
			WSACleanup();
			return 0;
		}
		printf("The data was sent to %s successfully!\n", inet_ntoa(serAddr.sin_addr));
		if (strcmp(buf, "exit") == 0)
		{
			break;
		}
		memset(buf, 0, sizeof(buf));
		if ((nRet = recvfrom(clisocket, buf, sizeof(buf), 0, (SOCKADDR*)&serAddr, &serAddrsize)) == SOCKET_ERROR)
		{
			closesocket(clisocket);
			WSACleanup();
			printf("recv failed\n");
			getchar();
			return 0;
		}
		printf("The data was received from %s successfully!\n",inet_ntoa(serAddr.sin_addr));
		puts(buf);
	}
	closesocket(clisocket);
	WSACleanup();
	return 0;
}

好了,windows下的UDP套接字通信还算成功
接下来是Android与PC的通信
我打算将PC端作为服务端
因此,PC端的程序就是上面原封不动的服务端程序
我用PC开热点,手机连上,cmd输入ipconfig查看网关为192.168.137.1因此配置该成IP
好,下面是安卓的客户端

Android客户端:
(这里我只写了发送)
首先,我自定义了一个View类,然后在上面加了UDP发送的方法

package com.example.xyt.helloandroid;

import android.content.Context;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.View;

import java.net.DatagramSocket;
import java.net.*;
import java.io.*;

/**
 * Created by xyt on 2015/10/9.
 */
public class MyView extends View{
    DatagramSocket socket;
    String msg="asd";

    public MyView(Context context) {
        super(context);
    }
    public boolean onTouchEvent(MotionEvent event) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                send();
            }
        }).start();;
        return false;
    }
    protected void onDraw(Canvas canvas) {

    }

    public void send(){
        StringBuilder sb = new StringBuilder();
        InetAddress local = null;
        try{
            local=InetAddress.getByName("192.168.137.1");
            System.out.println("已找到服务器,连接中..."+local);
        }catch(UnknownHostException e){
            System.out.println("未找到服务器"+e);
        }

        try{
            socket=new DatagramSocket();
            System.out.println("正在连接服务器...");
        }catch(SocketException e){
            System.out.println("服务器连接失败"+e);
        }
        int msg_len=msg.length();
        try {
            byte[] buf = msg.getBytes();
            DatagramPacket packet = new  DatagramPacket(buf, msg_len,local,4567);
            System.out.println("消息准备完毕,将要发送");
            socket.send(packet);
            System.out.println("消息发送成功");
        }catch (IOException e){
            System.out.println("消息发送失败"+e);
        }
        socket.close();
    }

}
该程序实现的功能:
每按一次屏幕,发一次数据包,内容是“asd”
这边有几点需要注意
1。套接字相关的东西,Java中貌似都需要catch异常处理,不然就会报错
2。像这里调用send需要另开一个线程
最重要的是,在AndroidManifest.xml里打开权限
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.SET_TIME_ZONE"/>
这个加在<application>的外面
当然,其实就只需要加一个就行
<uses-permission android:name="android.permission.INTERNET"/>

最后,在MainActivity.java里加上
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    view=new MyView(this);
    setContentView(view);
    Log.i(Activity_ID, "onCreate!");
}

就大功告成了














  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值