Android Socket编程实例

最近一段时间在断断续续地学习Android应用开发的一些知识,许多APP运行时都要服务器进行通信,socket可以很好完成这样一个功能。我在网上找到了一些手机和服务器通过socket通信的例子,然后挑了其中两个进行整合,供给像我一样的Android socket初学者进行参考。

两个例子的链接:

例子一:http://blog.csdn.net/wuchuanpingstone/article/details/6617276

例子二:http://blog.csdn.net/x605940745/article/details/17001641

我把两个例子整合成以下内容:


一、Android socket使用时要注意的地方

1、在Android主线程中不能有访问socket的操作,否则会报异常。

2、在Android工程配置文件中要进行网络权限声明: <uses-permission   android:name="android.permission.INTERNET"/>

      3、对数据进行发送接收操作时,首先获取socket流,然后可以封装成BufferedWriter和BufferedReader:

     br = new BufferedReader(new InputStreamReader(s.getInputStream()));//把socket输入流封装成BufferedReader
     os=new PrintWriter(new BufferedWriter(new OutputStreamWriter(s.getOutputStream())), true);//把socket输出流封装成PrintWriter
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">4、对socket进行读写之前还要判断,连接是否还存在:</span>
		if(!s.isClosed()&&s.isConnected()){
	           //进行socket读写操作<span style="white-space:pre">								
                 }
     

5、由于在主线程中不能访问网络的操作,所以socket通信还涉及到多线程的知识点;同样,UI控件的更新只能在主线程中进行,所以还涉及到Android消息处理机制相关知识点。


二、实例代码

Android客户端代码:

AndroidManifest.xml配置文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.client"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-permission   
    android:name="android.permission.INTERNET"/> 
    
    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


activity_main:

<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:id="@+id/input"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:hint="to send to the server" />  
    <Button   
        android:id="@+id/send"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:text="send"  
        android:layout_below="@id/input"/>  
    <TextView   
        android:id="@+id/show"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_below="@id/send"/>
    
    
    

</LinearLayout>



MainActivity.java:

package com.example.client;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


public class MainActivity extends Activity {

	// 定义界面上的两个文本框  
    EditText input;  
    TextView show;  
    // 定义界面上的一个按钮  
    Button send;  
    Handler handler;  
    // 定义与服务器通信的子线程  
    ClientThread clientThread; 
	
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        input = (EditText) findViewById(R.id.input);  
        show = (TextView) findViewById(R.id.show);  
        send = (Button) findViewById(R.id.send);  
        
        
        handler = new Handler() {  
  
            @Override  
            public void handleMessage(Message msg) {  
                // 如果消息来自子线程  
                if (msg.what == 0x123) {  
                    // 将读取的内容追加显示在文本框中  
                    show.append("\n" + msg.obj.toString());  
                }  
            }  
        };  
        
        clientThread = new ClientThread(handler);  
        // 客户端启动ClientThread线程创建网络连接、读取来自服务器的数据  
        new Thread(clientThread).start();  
        
        
        send.setOnClickListener(new OnClickListener() {  
  
            @Override  
            public void onClick(View v) {  
                try {  
                    // 当用户按下按钮之后,将用户输入的数据封装成Message  
                    // 然后发送给子线程Handler  
                    Message msg = new Message();  
                    msg.what = 0x345;  
                    msg.obj = input.getText().toString();  
                    clientThread.revHandler.sendMessage(msg);  
                    input.setText("");  
  
                } catch (Exception e) {  
  
                }  
            }  
        });  
        
        
    }


     
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

ClientThread.java:

package com.example.client;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

public class ClientThread implements Runnable {

	private Socket s;  
    // 定义向UI线程发送消息的Handler对象  
    Handler handler;  
    // 定义接收UI线程的Handler对象  
    Handler revHandler;  
    // 该线程处理Socket所对用的输入输出流  
    BufferedReader br = null;  
    //OutputStream os = null;
    PrintWriter os = null;
    
    public ClientThread(Handler handler) {  
        this.handler = handler;  
    }  

    @Override  
    public void run() {  //接收数据线程是发送数据线程的子线程
        s = new Socket();  
        try {  
            s.connect(new InetSocketAddress("121.248.52.236", 3000), 5000);  
            br = new BufferedReader(new InputStreamReader(s.getInputStream()));  
           // os = s.getOutputStream(); 
            os=new PrintWriter(new BufferedWriter(new OutputStreamWriter(s.getOutputStream())), true);
            // 启动一条子线程来读取服务器相应的数据  
            new Thread(new Runnable() {  
  
                @Override  
                public void run() {  
                    String content = null;  
                    // 不断的读取Socket输入流的内容  
                    try {  
                        while ((content = br.readLine()) != null) {  
                            // 每当读取到来自服务器的数据之后,发送的消息通知程序  
                            // 界面显示该数据  
                        	if(!s.isClosed()&&s.isConnected()){
                        		Message msg = new Message();  
                        		msg.what = 0x123;  
                            	msg.obj = content;  
                            	handler.sendMessage(msg);  
                        	}
                        }  
                    } catch (IOException io) {  
                        io.printStackTrace();  
                    }  
                }  
  
            }).start();  
            // 为当前线程初始化Looper  
            Looper.prepare();  
            // 创建revHandler对象  
            revHandler = new Handler() {  
  
                @Override  
                public void handleMessage(Message msg) {  
                    // 接收到UI线程的中用户输入的数据  
                    if (msg.what == 0x345) {  
                        // 将用户在文本框输入的内容写入网络  
                        try { 
                        	if(!s.isClosed()&&s.isConnected()){
                        		//os.write((msg.obj.toString() + "\r\n").getBytes("gbk"));  
                        		os.println(msg.obj.toString());
                        	}
                        } catch (Exception e) {  
                            e.printStackTrace();  
                        }  
                    }
                    
                    
                }  
  
            };   
            // 启动Looper  
            Looper.loop();  
  
        } catch (SocketTimeoutException e) {  
            Message msg = new Message();  
            msg.what = 0x123;  
            msg.obj = "网络连接超时!";  
            handler.sendMessage(msg);  
        } catch (IOException io) {  
            io.printStackTrace();  
        }  
  
    }  

	

}

Java服务端代码:


MyService.java:

package com.android.net;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class MyService {

	// 定义保存所有的Socket  
    public static List<Socket> socketList = new ArrayList<Socket>();  
  
    public static void main(String[] args) throws IOException {  
    	System.out.println("Server start...");
        ServerSocket server = new ServerSocket(3000);  
        while(true){  
            Socket s=server.accept();  
            socketList.add(s);  
            //每当客户端连接之后启动一条ServerThread线程为该客户端服务  
            new Thread(new ServiceThreada(s)).start();  
              
        }  
    }  

}


ServiceThreada.java:

package com.android.net;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

public class ServiceThreada implements Runnable {

	 // 定义当前线程处理的Socket  
    Socket s = null;  
    // 该线程所处理的Socket所对应的输入流  
    BufferedReader br = null;  
  
    public ServiceThreada(Socket s) {  
        this.s = s;  
        try {  
            br = new BufferedReader(new InputStreamReader(s.getInputStream()));  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
  
    @Override  
    public void run() {  
  
        String content = null;  
        //采用循环不断的从Socket中读取客户端发送过来的数据  
        while((content=readFromClient())!=null){  
            //遍历socketList中的每个Socket  
            //将读取到的内容每个向Socket发送一次  
           // for(Socket s:MyService.socketList)  
        	if(!s.isClosed()&&s.isConnected()){
                //OutputStream os;
        		PrintWriter os=null;
                try {
                	 //os = s.getOutputStream(); 
                	os=new PrintWriter(new BufferedWriter(new OutputStreamWriter(  
                            s.getOutputStream())), true);
                	if(content.equals("quit")){
                		System.out.println("user"+s.getInetAddress()+"offline");
                		//os.write(("From server:"+"user"+s.getInetAddress()+"offline"+"\n").getBytes("gbk"));
                		os.println("From server:user:"+s.getInetAddress()+"offline");
                		s.close();
                	}else{
                    	System.out.println("From client:"+content);
                    	//os.write(("From server:"+content+"\n").getBytes("gbk"));
                    	os.println("From server:"+content);
                	}
                } catch (IOException e) {  
                    // TODO Auto-generated catch block  
                    e.printStackTrace();  
                }  
                  
            }  
        }  
  
    }  
  
    // 定义读取客户端的信息  
    public String readFromClient() {  
        try {  
        	if(!s.isClosed()&&s.isConnected()){
        		return br.readLine();  
        	}
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return null;  
    }  
	

}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值