首页 > 代码库 > 天地币:所用到的 Android Socket 通讯编程技术试验

天地币:所用到的 Android Socket 通讯编程技术试验

1、为了开发“天地币”这个Android手机项目,需要用到Socket编程。

2、天地币是一种类似于比特币的虚拟货币。

3、为了赚取CSDN的C币,需要写篇博客。

4、干脆将调试Socket的项目发出来跟网友分享。


闲话休提,直接上代码,首先是字符串的定义:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">xyzSocket</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="ipaddr_str">本机IP:</string>
    <string name="serveripaddr_str">服务器IP:</string>
    <string name="server_str">设置为服务端</string>
    <string name="client_str">连接为客户端</string>
    <string name="mymachine_str">本机就是</string>
    <string name="send_str">发送</string>
    <string name="online_str">0在线</string>
    <string name="threeline_str">第1行\n第2行\n第3行\n</string>
    
</resources>

其次是xml文件:

<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.example.xyzsocket.MainActivity$PlaceholderFragment" >
    
    <RelativeLayout
        android:id="@+id/relativelayout_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
    
    	<TextView
        	android:id="@+id/ipaddr_label_1"
        	android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:layout_centerVertical="true"
        	android:text="@string/ipaddr_str" 
        	/>
    	
    	<EditText
        	android:id="@+id/myipaddr_edit"
        	android:layout_width="match_parent"
        	android:layout_height="wrap_content"
        	android:layout_toRightOf="@+id/ipaddr_label_1"
        	android:layout_toLeftOf="@+id/noline_label_1"
    	    />
    	
    	<TextView
        	android:id="@+id/online_label_1"
        	android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:layout_alignParentRight="true"
        	android:layout_centerVertical="true"
        	android:text="@string/online_str" 
    	    />
        
    </RelativeLayout>
    
    <RelativeLayout
        android:id="@+id/relativelayout_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/relativelayout_1"
        >
    	
    	<EditText
        	android:id="@+id/server_receiver"
        	android:layout_width="match_parent"
        	android:layout_height="wrap_content"
        	android:maxLines="3"
        	android:text="@string/threeline_str"
    	    />
        
    </RelativeLayout>
    
    <RelativeLayout
        android:id="@+id/relativelayout_3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/relativelayout_2"
        >
    	    
    	<TextView
        	android:id="@+id/ipaddr_label_2"
        	android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:layout_centerVertical="true"
        	android:text="@string/serveripaddr_str" 
        	/>
    	
    	<EditText
        	android:id="@+id/serveripaddr_edit"
        	android:layout_width="match_parent"
        	android:layout_height="wrap_content"
        	android:layout_toRightOf="@+id/ipaddr_label_2"
        	android:layout_toLeftOf="@+id/serveripaddr_check"
    	    />
    	
    	<CheckBox
        	android:id="@+id/serveripaddr_check"
        	android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:layout_alignParentRight="true"
        	android:layout_centerVertical="true"
        	android:text="@string/mymachine_str"
    	    />
        
    </RelativeLayout>
    
    <RelativeLayout
        android:id="@+id/relativelayout_4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/relativelayout_3"
        >
    	
    	<EditText
        	android:id="@+id/send_message"
        	android:layout_width="match_parent"
        	android:layout_height="wrap_content"
        	android:layout_toLeftOf="@+id/butt_send"
    	    />
        	
        <Button
	        android:id="@+id/butt_send"
    	    android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:layout_alignParentRight="true"
        	android:text="@string/send_str"
            />

        <LinearLayout
    	    android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:layout_centerHorizontal="true"
        	android:orientation="horizontal"
        	android:layout_below="@+id/send_message"
            >
            	
        <Button
	        android:id="@+id/butt_server"
    	    android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:text="@string/server_str"
	        android:layout_below="@+id/send_message"
            />
        	
        <Button
	        android:id="@+id/butt_client"
    	    android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:text="@string/client_str"
	        android:layout_below="@+id/send_message"
            />
        
        </LinearLayout>
        
    </RelativeLayout>
    
</RelativeLayout>

最主要的是代码:

package com.example.xyzsocket;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.os.Build;

public class MainActivity extends ActionBarActivity {

	private EditText et01 = null;
	private EditText et02 = null;
	private EditText et03 = null;
	private EditText et04 = null;
	private Button bn01 = null;
	private Button bn02 = null;
	private Button bn03 = null;
	private CheckBox cb01 = null;
	private TextView tv01 = null;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		if (savedInstanceState == null) {
			getSupportFragmentManager().beginTransaction()
					.add(R.id.container, new PlaceholderFragment()).commit();
		}
	}

	private String intToIp(int i){
		return (i & 0xFF) + "." + ((i>>8) & 0xFF) + "." + ((i>>16) & 0xFF) + "." + ((i>>24) & 0xFF);
	}

	@Override
	public void onWindowFocusChanged(boolean hasFocus) {
		// TODO Auto-generated method stub
		super.onWindowFocusChanged(hasFocus);
		if( et01 == null ){
			et01 = (EditText) findViewById(R.id.myipaddr_edit);
			if(et01 != null){
				WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
				if(!wifiManager.isWifiEnabled()){
					wifiManager.setWifiEnabled(true);
				}
				WifiInfo wifiInfo = wifiManager.getConnectionInfo();
				int ipAddress = wifiInfo.getIpAddress();
				et01.setText(intToIp(ipAddress));				
			}
		}
		if( et02 == null ){
			et02 = (EditText) findViewById(R.id.server_receiver);
			if(et02 != null){
			}
		}
		if( et03 == null ){
			et03 = (EditText) findViewById(R.id.serveripaddr_edit);
			if(et03 != null){
			}
		}
		if( et04 == null ){
			et04 = (EditText) findViewById(R.id.send_message);
			if(et04 != null){
				et04.setEnabled(false);
			}
		}
		if( bn01 == null ){
			bn01 = (Button) findViewById(R.id.butt_server);
			if( bn01 != null ){
				bn01.setOnClickListener(new View.OnClickListener() {
					
					@Override
					public void onClick(View v) {
						// TODO Auto-generated method stub
					    new Thread(){  
					        @Override  
					        public void run()  
					        {  
					        	//网络访问的代码放在这里     
								server();
					        }  
					    }.start();  					
					}
				});
			}
		}
		if( bn02 == null ){
			bn02 = (Button) findViewById(R.id.butt_client);
			if( bn02 != null ){
				bn02.setOnClickListener(new View.OnClickListener() {
					
					@Override
					public void onClick(View v) {
						// TODO Auto-generated method stub
					    new Thread(){  
					        @Override  
					        public void run()  
					        {  
					        	//网络访问的代码放在这里     
								client();
					        }  
					    }.start();  					
					}
				});
			}
		}
		if( bn03 == null ){
			bn03 = (Button) findViewById(R.id.butt_send);
			if( bn03 != null ){
				bn03.setOnClickListener(new View.OnClickListener() {
					
					@Override
					public void onClick(View v) {
						// TODO Auto-generated method stub
					    new Thread(){  
					        @Override  
					        public void run()  
					        {  
					        	//网络访问的代码放在这里     
								sendmsg();
					        }  
					    }.start();  					
					}
				});
				bn03.setEnabled(false);
			}
		}
		if( cb01 == null ){
			cb01 = (CheckBox) findViewById(R.id.serveripaddr_check);
			if( cb01 != null ){
				cb01.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
					
					@Override
					public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
						// TODO Auto-generated method stub
						Message msg = new Message();
						msg.arg1 = isChecked?1:0;
						msg.what = 103;
						handler.sendMessage(msg);
					}
				});
			}
		}
		if( tv01 == null ){
			tv01 = (TextView) findViewById(R.id.online_label_1);
			if( tv01 != null ){
				
			}
		}
	}

	@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);
	}

	/**
	 * A placeholder fragment containing a simple view.
	 */
	public static class PlaceholderFragment extends Fragment {

		public PlaceholderFragment() {
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.fragment_main, container,
					false);
			return rootView;
		}
	}
	
	private Handler handler = new Handler(){

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);
			myHandleMessage(msg);
		}
		
	};
	
	private void myHandleMessage(Message msg){
		switch(msg.what){
		case 101:
			bn01.setText("服务器中止");
			break;
		case 102:
        	bn01.setText(getString(R.string.server_str));
			break;
		case 103:
			if(msg.arg1>0){
				et03.setText(et01.getText().toString());
			}
			break;
		case 104:
			bn02.setText(msg.arg1>0?"客户端中止":getString(R.string.client_str));
			bn03.setEnabled(msg.arg1>0);
			et04.setEnabled(msg.arg1>0);
			break;
		case 110:
			String str = et02.getText().toString();
			int i = str.indexOf("\n");
			if(i>0){
				str = str.substring(i+1);
			}
			str += (String)msg.obj;
			str += "\n";
			et02.setText(str);
			break;
		case 111:
			Log.i("DEBUG", "客户端收到:" + (String)msg.obj);
			break;
		case 112:
			Log.i("DEBUG", "服务器中止了!!");
			tv01.setText("" + list.size() + "在线");
			bn02.setText(getString(R.string.client_str));
			bn03.setEnabled(false);
			et04.setEnabled(false);
			break;
		case 113:
			Log.i("DEBUG", "客户端退出了!!");
			tv01.setText("" + list.size() + "在线");
			break;
		case 114:
			tv01.setText("" + list.size() + "在线");
			break;
		}
	}
	
    ServerSocket aServerSocket = null;  
    ArrayList list = new ArrayList();  

	private void server(){
		myServerThread thread;
		if( aServerSocket != null ){
			try{
				aServerSocket.close();
				aServerSocket = null;
			}catch(IOException e){
				e.printStackTrace();
			}
	        if( bn01 != null )
	        {
	        	Message msg = new Message();
	        	msg.what = 102;
	        	handler.sendMessage(msg);
	        }
			return;
		}
        try {  
        	aServerSocket = new ServerSocket(55555);
        	Log.i("DEBUG", "already listen 55555 port.");  
        } catch (Exception e) {  
        	e.printStackTrace();  
        }  
        if(aServerSocket == null){
        	Log.i("DEBUG", "侦听失败了!!");
        	return;
        }
    	Log.i("DEBUG", "侦听成功了!!");
        if( bn01 != null )
        {
        	Message msg = new Message();
        	msg.what = 101;
        	handler.sendMessage(msg);
        }
        int num = 0;  
        while (num < 10) {  
        	Socket aSessionSoket = null;  
        	try {  
            	Log.i("DEBUG", "侦听前!!");
        		aSessionSoket = aServerSocket.accept();  
            	Log.i("DEBUG", "侦听后!!");
        		thread = new myServerThread(aSessionSoket);  
        		thread.start();
        		Message msg = new Message();
        		msg.what = 114;
        		handler.sendMessage(msg);
        	} catch (IOException e1) {  
        		// TODO Auto-generated catch block  
        		e1.printStackTrace();  
            	Log.i("DEBUG", "服务器手动中止了!!");
            	for(int i=0;i<list.size();i++){
            		Socket s = (Socket)list.get(i);
            		try{
            			s.close();
            		}catch(IOException e){
            			e.printStackTrace();
            		}
            	}
            	list.clear();
            	break;
        	}  
    		num = list.size();
    		Log.i("DEBUG", "socket count = " + num);
	    }		
	}
	  
	class myServerThread extends Thread {  
		public Socket aSessionSoket = null;  

		public myServerThread(Socket socket) {  
			aSessionSoket = socket;  
			list.add(socket);  
		}  
	  
		public void run() {  
		    DataInputStream aDataInput = null;  
		    DataOutputStream aDataOutput = null;  
			try {  
				aDataInput = new DataInputStream(aSessionSoket.getInputStream());  
				aDataOutput = new DataOutputStream(aSessionSoket.getOutputStream());  
				while (true) {  
	            	Log.i("DEBUG", "服务器接收前!!");
					String str = aDataInput.readUTF(); // read msg.
	            	Log.i("DEBUG", "服务器接收后!!");
					Message msg = new Message();
					msg.obj = str;
					msg.what = 110;
					handler.sendMessage(msg);
					aDataOutput.writeUTF("OK:" + str);
				}
	  
			} catch (IOException e) {  
	            // TODO Auto-generated catch block  
				e.printStackTrace();
				
			} finally {  
				try {
					if (aDataInput != null)
						aDataInput.close();
					if (aDataOutput != null)  
						aDataOutput.close();  
					list.remove(aSessionSoket);  
					aSessionSoket.close();
					// 这里的退出是客户端主动断开
					Message msg = new Message();
					msg.what = 113;
					handler.sendMessage(msg);
				} catch (Exception e2) {  
					e2.printStackTrace();  
				}  	  
			}  	  
		}  
	}
	
	Socket clientsocket = null;
	
	private void client(){
		Message msg;
		if( clientsocket != null ){
			try{
				clientsocket.close();
				clientsocket = null;
			}catch(IOException e){
				e.printStackTrace();
				return;
			}
        	msg = new Message();
        	msg.what = 104;
        	msg.arg1 = 0;
        	handler.sendMessage(msg);
			return;
		}
		InetAddress serverAddr;
		try {
			serverAddr = InetAddress.getByName ( et03.getText().toString() );
			Log.d ( "DEBUG" , "C: Connecting..." );
			// 与服务器获取连接
			clientsocket = new Socket(serverAddr, 55555);
			
		} catch (UnknownHostException e1) {
           // TODO Auto-generated catch block
           e1.printStackTrace();
		} catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
		}
		if(clientsocket == null){
        	Log.i("DEBUG", "连接失败了!!");
			return;
		}
        if( bn03 != null )
        {
        	msg = new Message();
        	msg.what = 104;
        	msg.arg1 = 1;
        	handler.sendMessage(msg);
        }
		myClientThread thread = new myClientThread(clientsocket);  
		thread.start();  
	}
	  
	class myClientThread extends Thread {  
		public Socket aSessionSoket = null;  

		public myClientThread(Socket socket) {  
			aSessionSoket = socket;  
		}  
	  
		public void run() {  
		    DataInputStream aDataInput = null;  
			try {  
				aDataInput = new DataInputStream(aSessionSoket.getInputStream());  
				while (true) {  
	            	Log.i("DEBUG", "客户端接收前!!");
					String str = aDataInput.readUTF();
	            	Log.i("DEBUG", "客户端接收后!!");
					Message msg = new Message();
					msg.obj = str;
					msg.what = 111;
					handler.sendMessage(msg);
				}
	  
			} catch (IOException e) {  
	            // TODO Auto-generated catch block  
				e.printStackTrace();
				Message msg = new Message();
				msg.what = 112;
				handler.sendMessage(msg);
				
			} finally {  
				try {
					if (aDataInput != null)
						aDataInput.close();
					aSessionSoket.close();
				} catch (Exception e2) {  
					e2.printStackTrace();  
				}  	  
			}  	  
		}  
	}
	
	private void sendmsg(){
	    DataOutputStream aDataOutput = null;
	    String message = et04.getText().toString();
	    if(message.isEmpty()){
	    	return;
	    }
		try {
			Log.i ( "DEBUG" , "C: Sending: '" + message + "'" );
			aDataOutput = new DataOutputStream(clientsocket.getOutputStream());
			aDataOutput.writeUTF(message);
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
		}
		
	}
	
}

别忘了添加权限:

	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>   
	<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>   
	<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
	<uses-permission android:name="android.permission.INTERNET"></uses-permission>

最后简单说说用法:

1、软件自动检测到自己wifi的IP地址。

2、一台机器可以同时扮演服务器和客户端。

3、其他机器可以登录到同一台服务器。


网络通讯,就这么简单。






天地币:所用到的 Android Socket 通讯编程技术试验