Socket通信,PC-pc,pc-Android



Socket通信

PCPC,PCAndroidSocket通信

本程序已经本人虚拟机,实体机验证。Android版本在4.0以上。

本人是初学者,因为喜欢业余做游戏,涉及到socket通信,参考许多资料和网上各位大神传的程序,还是遇到许多bug,经过一点点的查找整理,调试,分析,终于通信成功。本文服务端是一对多通信,使用本人的PC机做服务端,客户端分别用:本人PC机,Android模拟器(4.4.2),以及公司用的mid(android系统的平板电脑)

需要注意的地方:服务端采用线程来处理每个客户端的通信,客户端(尤其是Android4.0以上版本)采用线程来发送接收数据与服务端通信(刚开始没有采用线程,直接搬网上一些大神的程序,他们许多是在2.3版本做的,在4.0以上版本总是出问题)。另外需要注意:控件不能在子线程中修改,按键监控,线程判断等。

下面贴出程序:

PC机主控端:

a.主程序

importjava.io.IOException;

import java.net.ServerSocket;

importjava.net.Socket;

public class MultiServer {

   public static double area=0;

   public MultiServer() {

      // TODOAuto-generated constructor stub

   }

   public static void main(String[] args) {

      // TODOAuto-generated method stub

      try{

         System.out.println("服务器启动了");

        ServerSocket serverSocket = new ServerSocket(12345);

        Socket connectToClient = null;

        while(true){//这是一个无限循环

           //等待客户请求

           connectToClient =serverSocket.accept();

           //

           new ServerThread(connectToClient);

        }

      }catch(IOException e){

        e.printStackTrace();

      }

   }

}

b.线程处理程序:

importjava.io.DataInputStream;

importjava.io.DataOutputStream;

importjava.io.IOException;

importjava.net.Socket;

 

 

public class ServerThread extends Thread {

   private Socket connectToClient;//声名套接字

   private DataInputStream inFromClient;//声名数据输入流

   private DataOutputStream outToClient;//声名数据输出流

   //private double area=0;

  

   public ServerThread(Socket socket) throws IOException {

      // TODOAuto-generated constructor stub

      super();

      connectToClient = socket; //实例化

      inFromClient = newDataInputStream(connectToClient.getInputStream());

      outToClient = new DataOutputStream(connectToClient.getOutputStream());

      start();//启动run()方法

   }

   public void run(){

      String str;

      double radius=0;//area=0;

      boolean goon = true;

      try{

       

        System.out.println("有客户端连接到服务器了");

        while(goon){

           str = inFromClient.readUTF();

           if(!str.equals("bye")){

              if(str.equals("接受")){

                 str = inFromClient.readUTF();

                 radius = Double.parseDouble(str);

                 System.out.println("接收到的半径值为:" +radius);

                 MultiServer.area = radius*radius*Math.PI;

                 str = Double.toString(MultiServer.area);

                 System.out.println("圆面积是"+str);

                 outToClient.writeUTF("我已经准备好了,快来接收吧");

                 outToClient.flush();

                 System.out.println("连接服务器成功了");

              }

              //str = inFromClient.readUTF();

              else if(str.equals("发送")){

                

                 System.out.println("要发送的圆面积是:" +MultiServer.area);

                 str = Double.toString(MultiServer.area);

                 outToClient.writeUTF(str);

                 outToClient.flush();

                 System.out.println("圆面积"+str+"已经发送");

                 System.out.println("连接服务器成功了");

             

              }

           }else{

              goon = false;

              outToClient.writeUTF("bye");

              outToClient.flush();

              System.out.println("连接服务器结束了");

           }

        }

        inFromClient.close();

        outToClient.close();

        connectToClient.close();

      }catch(IOException e){

        e.printStackTrace();

      }

   }

 

   public ServerThread(Runnable target) {

      super(target);

      // TODOAuto-generated constructor stub

   }

 

   public ServerThread(String name) {

      super(name);

      // TODOAuto-generated constructor stub

   }

 

   public ServerThread(ThreadGroup group, Runnable target) {

      super(group, target);

      // TODOAuto-generated constructor stub

   }

 

   public ServerThread(ThreadGroup group, String name) {

      super(group, name);

      // TODOAuto-generated constructor stub

   }

   public ServerThread(Runnable target, String name) {

      super(target, name);

      // TODOAuto-generated constructor stub

   }

   public ServerThread(ThreadGroup group, Runnable target, String name) {

      super(group, target, name);

      // TODOAuto-generated constructor stub

   }

   public ServerThread(ThreadGroup group, Runnable target, String name,

        long stackSize) {

      super(group, target, name, stackSize);

      // TODOAuto-generated constructor stub

   }

 

}

2.pc机客户端:

importjava.io.BufferedReader;

importjava.io.DataInputStream;

importjava.io.DataOutputStream;

importjava.io.IOException;

importjava.io.InputStreamReader;

import java.net.Socket;

 

 

public class Client {

 

   public Client() {

      // TODOAuto-generated constructor stub

   }

 

   public static void main(String[] args) {

      // TODOAuto-generated method stub

      try{

        //连接到本机,端口号是5500

        Socket connectToServer = new Socket("localhost",12345);

        //将数据输入流连接到socket

        DataInputStream inFromServer = new DataInputStream(

           connectToServer.getInputStream());

        //将数据输出流连接到socket

        DataOutputStream outToServer = new DataOutputStream(

           connectToServer.getOutputStream());

        System.out.println("输入半径数值发送到服务器,输入bye结束。");

        String outStr,inStr;

        boolean goon = true;

        BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));

        //反复读用户数据并计算

        while(goon){

           outToServer.writeUTF("接受");

           outToServer.flush();

          

           outStr = buf.readLine();//读入用户输入

           outToServer.writeUTF(outStr);

           outToServer.flush();

          

           inStr = inFromServer.readUTF();

           System.out.println("收到的握手信号是: "+inStr);

           if(inStr.equals("我已经准备好了,快来接收吧"))

           {

              //System.out.println("程序走到这一步了吗?");

              outToServer.writeUTF("发送");

              outToServer.flush();

              inStr = inFromServer.readUTF();

           }

          

           if(!inStr.equals("bye")){

              System.out.println("从服务器返回的结果是: "+inStr);

           }else{

              goon = false;

              System.out.println("从服务器返回的结果结束! ");

           }

          

        }

        inFromServer.close();

        outToServer.close();

        connectToServer.close();

        }catch(IOException e){

           e.printStackTrace();

      }

     

   }

 

}

3.Android客户端

a.Main.xml:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    

    android:layout_width="fill_parent"    

    android:layout_height="fill_parent"    

    android:orientation="vertical"> 

    <Button 

        android:id="@+id/rev"         

        android:text="接收显示"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>

    <Button 

        android:id="@+id/out"        

        android:text="获取发送"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>

    <EditText

        android:id="@+id/show"

        android:layout_width="wrap_content"       

        android:layout_height="wrap_content"

        android:hint="请输入半径值:"       

         />

    <!--android:text="请输入半径值:"  -->

    <EditText

        android:id="@+id/display"

        android:layout_width="wrap_content"       

        android:layout_height="wrap_content"

        android:hint="请查看圆面积为"        

         /> 

        <!--android:text="圆面积为:"  --> 

    <TextView

        android:id="@+id/receiver"

        android:layout_width="fill_parent"       

        android:layout_height="wrap_content"        

        android:text="IsTransproting...." /> 

     <!-- <TextView

        android:id="@+id/outputer"

       android:layout_width="fill_parent"       

       android:layout_height="wrap_content"        

        android:text="IsTransporting...." /> -->

     

</LinearLayout>

b.Mainfest

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.rocketandclient"

    android:versionCode="1"

    android:versionName="1.0">

 

    <uses-sdk

        android:minSdkVersion="14"

        android:targetSdkVersion="19"/>

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

    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme">

        <activity

            android:name="com.example.rocketandclient.Main"

            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>

主要是开机网络通信:<uses-permission android:name="android.permission.INTERNET"/>

C.Main.class

packagecom.example.rocketandclient;

 

import java.io.DataInputStream;

importjava.io.DataOutputStream;

importjava.io.IOException;

import java.io.InputStream;

importjava.net.InetAddress;

importjava.net.Socket;

importjava.net.UnknownHostException;

importcom.example.rocketandclient.R;

import com.example.rocketandclient.Main.outputerlistenr;

import com.example.rocketandclient.Main.receiverlistenr;

importandroid.app.Activity;

import android.app.ActionBar;

import android.app.Fragment;

importandroid.os.Bundle;

importandroid.os.Handler;

import android.os.Message;

importandroid.util.Log;

import android.view.LayoutInflater;

import android.view.Menu;

import android.view.MenuItem;

importandroid.view.View;

import android.view.ViewGroup;

importandroid.view.View.OnClickListener;

import android.widget.Button;

importandroid.widget.EditText;

importandroid.widget.TextView;

import android.os.Build;

/***

 * 注意,以下采用两种方法实现添加线程

 * @author Administrator

 *

 */

public class Main extends Activity implements OnClickListener, Runnable {// //implements Runnable

   private Button btnRev=null;

   private Button btnOut=null;

   private TextView revtext=null;

   private EditText outText=null;

   private EditText displayText=null;

   private String str;

   private DataInputStream inRec=null;

   private DataOutputStream output=null;

   private InetAddress serverAddr ;

   private Thread th1,th2,th;

   private Socket mSocket;

// public final boolean sendMessage (Message msg);

// public void handleMessage (Message msg);

   @Override

   protected voidonCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);

     

      btnRev=(Button)findViewById(R.id.rev);    

        btnOut=(Button)findViewById(R.id.out);    

        outText=(EditText)findViewById(R.id.show);

        displayText=(EditText)findViewById(R.id.display);

        revtext=(TextView)findViewById(R.id.receiver);

        /*

         * 注意两种按键监听的写法,一种需要执行OnClickListener接口,

         * btnOut.setOnClickListener(this);

         *并且重写 @Override

       *public void onClick(View v)

       *一种:rev.setOnClickListener(new receiverlistenr());需要写内部类:

       *class receiverlistenr implements OnClickListener{

        *   public void onClick(View v) {   ;}}

       *

         */

        //rev.setOnClickListener(new receiverlistenr());

        //out.setOnClickListener(new outputerlistenr());

       

        btnRev.setOnClickListener(this);

        btnOut.setOnClickListener(this);

      /*if (savedInstanceState == null) {

        getFragmentManager().beginTransaction()

              .add(R.id.container, new PlaceholderFragment()).commit();

      }*/

   }

    class receiverlistenr implements OnClickListener{

         public void onClick(View v) {       // TODO Auto-generated method stub              

            Log.v(str, "接收操作");

             th2 = new Thread(new SocketInRun());

             th2.start();

               

                 

            }

           

         }

    

   class outputerlistenr implementsOnClickListener{

         public void onClick(View v) {       // TODO Auto-generated method stub

            Log.v(str, "进入发送操作");

             th1 = new Thread(new SocketOutRun());

             th1.start();    

            }

         }

   class SocketInRun implementsRunnable {

      @Override

       public void run(){

        try {       

            //实例化Socket 

            Socketsocket2 = null;

           

            serverAddr = InetAddress.getByName("192.168.9.124");

            socket2=new Socket("192.168.9.124",12345);

            output = new DataOutputStream(socket2.getOutputStream());

            output.writeUTF("发送");

            output.flush();

            //获得输入流

             inRec=new DataInputStream(socket2.getInputStream());

             String msg="";

             str=msg = inRec.readUTF();

             Log.v(str,"接收到的圆面积是:msg"+ str);

             //设置文本框的字符串   

             //displayText.setText(msg);

            //Main.revtext.setText(msg);//子线程内不能设置控件,否则程序崩溃

           

            Log.v(msg,"接收到的圆面积是:"+msg);

            inRec.close();

            socket2.close();

            }

         catch (UnknownHostException e) {     // TODOAuto-generated catch block    

               e.printStackTrace();

              }

         catch (IOException e) {     // TODOAuto-generated catch block   

               e.printStackTrace();

              }       

 

      }

      }

   class SocketOutRun implementsRunnable {

      @Override

       public void run(){

        try {       

            //实例化Socket

           

            Socketsocket1 = null;

            serverAddr = InetAddress.getByName("192.168.9.124");

            Log.v(str, "进入发送操作1");

            socket1=new Socket("192.168.9.124",12345);

            Log.v(str, "进入发送操作2");

            Stringmsg = outText.getText().toString();

            output = new DataOutputStream(socket1.getOutputStream());

            output.writeUTF("接受");

            output.flush();

            output.writeUTF(msg);

            output.flush();

            output.close();

           socket1.close();

            }

         catch (UnknownHostException e) {     // TODOAuto-generated catch block    

               e.printStackTrace();

              }

         catch (IOException e) {     // TODOAuto-generated catch block   

               e.printStackTrace();

              }

 

          } //catch(Exceptione){}

 

       }

@Override

public void onClick(View v) {

   // TODOAuto-generated method stub

   if(v == btnRev){

      Log.v(str, "接收操作");

      //th2 = new Thread(new SocketInRun());

      th2 = new Thread(this);//线程实例化

      th2.start();//线程启动

     

      //displayText.setText(str);

      //revtext.setText(str);

   }

   if(v == btnOut){

      Log.v(str, "进入发送操作");

      //th1 = new Thread(new SocketOutRun());

      th1 = new Thread(this);

      th1.start();

   }

  

}

@Override

public void run() {

   // TODOAuto-generated method stubthis

   th = new Thread(this);

   if(th.currentThread() == th1){//判断当前执行的是哪个线程,如果是线程1,操作发送程序

      Log.v(str, "1");

      try {       

        //实例化Socket

       

        Socket socket1 = null;

        serverAddr = InetAddress.getByName("192.168.9.124");

        Log.v(str, "进入发送操作1");

        socket1=new Socket("192.168.9.124",12345);

        Log.v(str, "进入发送操作2");

        String msg = outText.getText().toString();

        output = new DataOutputStream(socket1.getOutputStream());//实例化输出流

        output.writeUTF("接受");//写数据

        output.flush();//

        output.writeUTF(msg);

        output.flush();

        output.close();

        socket1.close();

         }

      catch (UnknownHostException e) {     // TODOAuto-generated catch block    

          e.printStackTrace();

         }

      catch (IOException e) {     // TODOAuto-generated catch block   

          e.printStackTrace();

           }

   }

   if(th.currentThread() == th2){//如果是进程2则操作下面接收到数据

      Log.v(str, "2");

      try {       

        //实例化Socket 

        Socket socket2 = null;

        String msg="";

       

        serverAddr = InetAddress.getByName("192.168.9.124");

        socket2=new Socket("192.168.9.124",12345);//设置机器所用的网络IP,要与PC机保持一致,端口自定义

        output = new DataOutputStream(socket2.getOutputStream());

        output.writeUTF("发送");

        output.flush();

        //获得输入流

          inRec=new DataInputStream(socket2.getInputStream());

         

          str=msg = inRec.readUTF();//读数据

         // msg = inRec.readUTF();

         Message msgg = new Message();

         msgg.what = 100;

          this.mHandler.sendMessage(msgg); 

 

        Log.v(msg,"接收到的圆面积是:"+msg);

        inRec.close();

        socket2.close();

         }

      catch (UnknownHostException e) {     // TODOAuto-generated catch block    

          e.printStackTrace();

         }

      catch (IOException e) {     // TODOAuto-generated catch block   

          e.printStackTrace();

           } 

     

   }

  

}

/*

 * 注意控件的设置不能在子线程中操作,需要在主线程中。

 * 需要子线程中参数来改变控件的请注意以下方法

 *

 */

privateHandler mHandler = new Handler() {

   public void handleMessage(Message msg) { 

      switch (msg.what){

      case 100:

        displayText.setText(str);

        revtext.setText(str);   

        break; 

        }

      }

      };

 

  

      }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值