Android socket AsyncTask和linux服务端通讯
16lz
2021-01-23
android 3以后,在UI主线程里面不能访问网络,因为访问网络可能导致程序崩溃,UI界面无法刷新,所以只有通过线程来完成,但对于线程许多人不是很清晰,而且代码会 很多,但是现在android提供了AsyncTask来处理异步任务。
客户端代码:
package com.test;import android.app.Activity;import android.os.AsyncTask;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.Socket;import java.net.UnknownHostException;public class MainActivity extends Activity implements View.OnClickListener { private TextView TextTime; private Button buttonTime; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextTime =(TextView)this.findViewById(R.id.textViewTime); buttonTime = (Button)this.findViewById(R.id.button2); buttonTime.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.button2: //注意每次需new一个实例,新建的任务只能执行一次,否则会出现异常 MyTask mTask = new MyTask(); mTask.execute("119.29.85.118"); break; default: break; } } private class MyTask extends AsyncTask<String,Integer,String>{ //onPreExecute方法用于在执行后台任务前做一些UI操作 @Override protected void onPreExecute() { TextTime.setText("fwe"); } //doInBackground方法内部执行后台任务,不可在此方法内修改UI protected String doInBackground(String... parms) { Socket socket =null; try { socket = new Socket(parms[0], 8888); System.out.println("socket has connected"); //2.得到socket读写流 OutputStream os=socket.getOutputStream(); OutputStreamWriter pw=new OutputStreamWriter (os); BufferedWriter bw = new BufferedWriter(pw); bw.write("TIME"); bw.flush(); // 从服务端程序接收数据 InputStream ips = socket.getInputStream(); InputStreamReader ipsr = new InputStreamReader(ips); BufferedReader br = new BufferedReader(ipsr); String s = ""; String result=""; while((s = br.readLine()) != null) { result += s; System.out.println(s); } socket.close(); return result; } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return "fweffwef"; } //onProgressUpdate方法用于更新进度信息 protected void onProgressUpdate(Integer... progress) { // progressBar.setProgress(progresses[0]); } //onPostExecute方法用于在执行完后台任务后更新UI,显示结果 protected void onPostExecute(String result) { TextTime.setText(result); } //onCancelled方法用于在取消执行中的任务时更改UI @Override protected void onCancelled() { } }}
添加网络访问权限:
<uses-permission android:name="android.permission.INTERNET"/>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.test.MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ButtonPost" android:id="@+id/buttonpost" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="64dp"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Button" android:id="@+id/button2" android:layout_below="@+id/buttonpost" android:layout_centerHorizontal="true" android:layout_marginTop="55dp"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Button" android:id="@+id/button3" android:layout_centerVertical="true" android:layout_alignLeft="@+id/button2" android:layout_alignStart="@+id/button2"/> <TextView android:layout_width="fill_parent" android:layout_height="70dp" android:text="Medium Text" android:id="@+id/textViewTime" android:layout_below="@+id/button3" android:layout_marginTop="68dp"/></RelativeLayout>
linux服务代码还是和上篇文章一样,所以说一般服务端开发代码都比较少:
#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <time.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <signal.h>#define BUFFLEN 1024#define SERVER_PORT 8888#define BACKLOG 5#define PIDNUMB 3static void handle_connect(int s_s){ int s_c; /*客户端套接字文件描述符*/ struct sockaddr_in from; /*客户端地址*/ socklen_t len = sizeof(from); /*主处理过程*/ while(1) { /*接收客户端连接*/ s_c = accept(s_s, (struct sockaddr*)&from, &len); time_t now; /*时间*/ char buff[BUFFLEN]; /*收发数据缓冲区*/ int n = 0; memset(buff, 0, BUFFLEN); /*清零*/ n = recv(s_c, buff, BUFFLEN,0); /*接收发送方数据*/ if(n > 0 && !strncmp(buff, "TIME", 4)) /*判断是否合法接收数据*/ { memset(buff, 0, BUFFLEN); /*清零*/ now = time(NULL); /*当前时间*/ sprintf(buff, "%24s\r\n",ctime(&now)); /*将时间复制入缓冲区*/ send(s_c, buff, strlen(buff),0); /*发送数据*/ } /*关闭客户端*/ close(s_c); }}void sig_int(int num){ exit(1); }int main(int argc, char *argv[]){ int s_s; /*服务器套接字文件描述符*/ struct sockaddr_in local; /*本地地址*/ signal(SIGINT,sig_int); /*建立TCP套接字*/ s_s = socket(AF_INET, SOCK_STREAM, 0); /*初始化地址和端口*/ memset(&local, 0, sizeof(local)); /*清零*/ local.sin_family = AF_INET; /*AF_INET协议族*/ local.sin_addr.s_addr = htonl(INADDR_ANY); /*任意本地地址*/ local.sin_port = htons(SERVER_PORT); /*服务器端口*/ /*将套接字文件描述符绑定到本地地址和端口*/ bind(s_s, (struct sockaddr*)&local, sizeof(local)); listen(s_s, BACKLOG); /*侦听*/ /*处理客户端连接*/ pid_t pid[PIDNUMB]; int i =0; for(i=0;i<PIDNUMB;i++) { pid[i] = fork(); if(pid[i] == 0) /*子进程*/ { handle_connect(s_s); } } while(1); close(s_s); return 0;}
程序实现的效果是,点击第二个按钮,在TextView上面显示从服务端获得的值。在本例中,也就是时间。
技术在不断的积累中慢慢变强。。。
更多相关文章
- Android GPS 定位 2 详细地址
- 知识梳理:Android子线程中更新UI的3种方法
- android中判断当前运行activity名的方法
- 葵花宝典之普及篇 —— HD2 android 各种直刷方法
- android中实现view的更新UI有两组方法的问题
- Could not find SDK_Root\tools\adb.exe 的解决方法
- Android高手进阶教程(八)-------Android中两种设置全屏的方法!!!
- android客户端首次进入轮播引导图(五)