Java 从android应用程序通过TCP发送数据

Java 从android应用程序通过TCP发送数据,java,android,tcp,Java,Android,Tcp,我正在尝试从android应用程序发送数据 客户端类src: import java.io.*; import java.net.Socket; import java.net.UnknownHostException; public class CClient implements Runnable { private Socket socket; private String ServerIP = "10.0.0.14"; public voi

我正在尝试从android应用程序发送数据 客户端类src:

import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;

public class CClient    
implements Runnable     
{
    private Socket socket;
    private String ServerIP = "10.0.0.14";


    public void run()
    {
        try 
        {
            socket = new Socket("10.0.0.14", 16606);

        }
        catch(Exception e) 
        {
            System.out.print("Whoops! It didn't work!:");
            System.out.print(e.getLocalizedMessage());
            System.out.print("\n");
        }
    }

    public void Send(String s)
    {
        try
        {
            PrintWriter outToServer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
            outToServer.print(s + "\n");
            outToServer.flush();


        }
        catch (UnknownHostException e) {
            System.out.print(e.toString());
        } catch (IOException e) {
            System.out.print(e.toString());
        }catch (Exception e) {
            System.out.print(e.toString());
        }

    }
}
在活动中使用CClient类创建连接并发送数据。 这是活动代码

import android.os.Bundle;
import android.app.Activity;
import android.view.*;
import android.widget.*;


public class Auth extends Activity {

    private ProgressBar mProgress;
    private TextView mTV;

    private CClient mClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auth);


        mProgress = (ProgressBar) findViewById(R.id.progressBar1);
        mTV =  (TextView) findViewById(R.id.textView4);

        mClient = new CClient();                
        Thread myThready = new Thread(mClient);
        myThready.start();  

    }

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

    public void proc_Login(View v)
    {

        for (int i=0; i<5; i++)
            mClient.Send("asaadsasdasd");
    }

}
导入android.os.Bundle;
导入android.app.Activity;
导入android.view.*;
导入android.widget.*;
公共类身份验证扩展活动{
私人进度律师程序;
私有文本视图mTV;
私人客户mClient;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u auth);
mProgress=(ProgressBar)findViewById(R.id.progressBar1);
mTV=(TextView)findViewById(R.id.textView4);
mClient=新的CClient();
线程准备=新线程(mClient);
myThready.start();
}
@凌驾
公共布尔onCreateOptions菜单(菜单){
//为菜单充气;这会将项目添加到操作栏(如果存在)。
getMenuInflater().充气(R.menu.auth,menu);
返回true;
}
公共作废程序登录(视图v)
{

对于(inti=0;i这段代码有效。我必须添加一个简单的按钮来触发proc_登录调用,我在我的服务器(debian)上用netcat-l-p8546进行了测试,每次按下按钮我都得到5个'asadsasdsd'。 netcat -l -p 8546 (我使用了端口8546,因为它已经在我的防火墙上打开了)

我当然加了一句

<uses-permission android:name="android.permission.INTERNET" /> 在AndroidManifest.xml文件中

也许您的服务器代码在收到一行代码后会关闭套接字

另外请注意,您不需要线程,异步任务更合适,尽管在本例中它可以工作

MainActivity.java:

package com.defranoux.testtcpsend;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

  private CClient mClient;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mClient = new CClient();                
    Thread myThready = new Thread(mClient);
    myThready.start();

    Button button1 = (Button) findViewById(R.id.button1);
    button1.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View arg0) {
        proc_Login(arg0);        
      }
    });    
  }


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

  public void proc_Login(View v)
  {
      for (int i=0; i<5; i++)
          mClient.Send("asaadsasdasd");
  }

}
package com.defranoux.testtcpsend;
导入android.os.Bundle;
导入android.app.Activity;
导入android.view.Menu;
导入android.view.view;
导入android.view.view.OnClickListener;
导入android.widget.Button;
公共类MainActivity扩展了活动{
私人客户mClient;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mClient=新的CClient();
线程准备=新线程(mClient);
myThready.start();
按钮button1=(按钮)findViewById(R.id.button1);
button1.setOnClickListener(新的OnClickListener(){
@凌驾
公共void onClick(视图arg0){
进程登录(arg0);
}
});    
}
@凌驾
公共布尔onCreateOptions菜单(菜单){
//为菜单充气;这会将项目添加到操作栏(如果存在)。
getMenuInflater().充气(R.menu.main,menu);
返回true;
}
公共作废程序登录(视图v)
{

对于(int i=0;i您永远不会清理与服务器的连接。您需要在刷新流后关闭这些输出流

outToServer.flush();
outToServer.close();

同样的结果,只发送了一条消息。奇怪。在客户端,您是否收到任何异常?没有任何异常。只有一次发送。越来越奇怪。任何更改都来自C#server(我猜它绑定、侦听、接受,然后在recv上循环)。您可以在服务器上运行wireshark来查看发生了什么,但这是最后一种手段……服务器工作正常。尝试用c#创建简单的tcp客户端,效果很好。您能否解释一下,当您在线程中所做的唯一工作是初始化套接字时,为什么将CClient作为单独的线程运行?send方法是st我将在主线程中执行,因为无法从主线程创建连接,只能从新线程创建连接。我想说的是,您也应该从新线程发送数据,而不是从mai线程发送数据。理想情况下,发送也应该在单独的线程中运行
outToServer.flush();
outToServer.close();