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 3
static 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上面显示从服务端获得的值。在本例中,也就是时间。
技术在不断的积累中慢慢变强。。。