由于项目需要,现在小白开始安卓网络编程的学习
安卓的网络编程分为
基于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!"); }
就大功告成了