Socket通信,PC-pc,pc-Android

来源:互联网 发布:java多线程面试 编辑:程序博客网 时间:2024/04/29 16:09


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;

publicclass MultiServer {

  publicstaticdoublearea=0;

  public MultiServer() {

     //TODOAuto-generated constructor stub

  }

  publicstaticvoid 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;

 

 

publicclass ServerThreadextends Thread {

  private SocketconnectToClient;//声名套接字

  private DataInputStreaminFromClient;//声名数据输入流

  private DataOutputStreamoutToClient;//声名数据输出流

  //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()方法

  }

  publicvoid 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();

             elseif(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;

 

 

publicclass Client {

 

  public Client() {

     //TODOAuto-generated constructor stub

  }

 

  publicstaticvoid 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:

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayoutxmlns: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

<?xmlversion="1.0"encoding="utf-8"?>

<manifestxmlns: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-permissionandroid: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>

               <actionandroid:name="android.intent.action.MAIN"/>

 

               <categoryandroid:name="android.intent.category.LAUNCHER"/>

           </intent-filter>

       </activity>

   </application>

 

</manifest>

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

C.Main.class

packagecom.example.rocketandclient;

 

import java.io.DataInputStream;

importjava.io.DataOutputStream;

importjava.io.IOException;

importjava.io.InputStream;

importjava.net.InetAddress;

importjava.net.Socket;

importjava.net.UnknownHostException;

importcom.example.rocketandclient.R;

importcom.example.rocketandclient.Main.outputerlistenr;

importcom.example.rocketandclient.Main.receiverlistenr;

importandroid.app.Activity;

importandroid.app.ActionBar;

importandroid.app.Fragment;

importandroid.os.Bundle;

importandroid.os.Handler;

import android.os.Message;

importandroid.util.Log;

importandroid.view.LayoutInflater;

importandroid.view.Menu;

importandroid.view.MenuItem;

importandroid.view.View;

importandroid.view.ViewGroup;

importandroid.view.View.OnClickListener;

import android.widget.Button;

importandroid.widget.EditText;

importandroid.widget.TextView;

importandroid.os.Build;

/***

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

 *@author Administrator

 *

 */

publicclass Mainextends Activityimplements OnClickListener, Runnable {// //implements Runnable

  private ButtonbtnRev=null;

  private ButtonbtnOut=null;

  private TextViewrevtext=null;

  private EditTextoutText=null;

  private EditTextdisplayText=null;

  private Stringstr;

  private DataInputStreaminRec=null;

  private DataOutputStreamoutput=null;

  private InetAddressserverAddr ;

  private Threadth1,th2,th;

  private SocketmSocket;

//public final boolean sendMessage (Message msg);

//public void handleMessage (Message msg);

  @Override

  protectedvoidonCreate(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(newreceiverlistenr());需要写内部类:

      *class receiverlistenr implements OnClickListener{

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

      *

        */

       //rev.setOnClickListener(newreceiverlistenr());

       //out.setOnClickListener(newoutputerlistenr());

       

       btnRev.setOnClickListener(this);

       btnOut.setOnClickListener(this);

     /*if (savedInstanceState == null) {

       getFragmentManager().beginTransaction()

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

     }*/

  }

   class receiverlistenrimplements OnClickListener{

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

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

            th2 = new Thread(new SocketInRun());

            th2.start();

              

                

           }

          

        }

   

  class outputerlistenrimplementsOnClickListener{

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

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

            th1 = new Thread(new SocketOutRun());

            th1.start();    

           }

        }

  class SocketInRunimplementsRunnable {

     @Override

      publicvoid 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 SocketOutRunimplementsRunnable {

     @Override

      publicvoid 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

publicvoid 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

publicvoid run() {

  //TODOAuto-generated methodstubthis

  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();

          } 

     

  }

  

}

/*

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

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

 *

 */

privateHandlermHandler =new Handler() {

  publicvoid handleMessage(Message msg) { 

     switch (msg.what){

     case 100:

       displayText.setText(str);

       revtext.setText(str);   

       break; 

       }

     }

     };

 

  

     }

0 0
原创粉丝点击