Android studio4.0.1中客户端tcp socket连接报错s.connect()报错,如何解决?(语言-java)

Android studio4.0.1中客户端tcp socket连接报错s.connect()报错。所有可能引起报错的因素均已经排除。


```java

    btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try{
                    //s=new Socket("192.168.1.105",8888);
                    s=new Socket();
                    SocketAddress socketAddr = new InetSocketAddress("192.168.1.105", 8888);
                    s.connect(socketAddr);
                    dout=new DataOutputStream(s.getOutputStream());
                    din=new DataInputStream(s.getInputStream());
                    dout.writeUTF("reg");
                    String msg=din.readUTF();
                    tv1.setText(msg);
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        });
    
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE">uses-permission>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE">uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">uses-permission>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE">uses-permission>
    
    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
当执行s.connect()时抛出异常android.os.NetworkOnMainThreadException

```

这个异常是因为在主线程中进行了网络操作,而Android不允许在主线程中进行耗时的网络操作。解决方法是将网络操作放在子线程中进行。可以使用AsyncTask或者Thread来实现。
使用AsyncTask的示例代码:

btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        new ConnectTask().execute("192.168.1.105", "8888");
    }
});

private class ConnectTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... params) {
        try {
            String ip = params[0];
            int port = Integer.parseInt(params[1]);
            s = new Socket(ip, port);
            dout = new DataOutputStream(s.getOutputStream());
            din = new DataInputStream(s.getInputStream());
            dout.writeUTF("reg");
            String msg = din.readUTF();
            return msg;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected void onPostExecute(String result) {
        if (result != null) {
            tv1.setText(result);
        }
    }
}


在上面的代码中,我们使用了AsyncTask来执行网络操作。在按钮的点击事件中,我们创建了一个ConnectTask实例,并调用execute方法来执行这个任务。execute方法会在子线程中执行doInBackground方法,该方法中进行网络操作。当网络操作完成后,会调用onPostExecute方法,在该方法中更新UI。注意,我们不能在doInBackground方法中更新UI,因为该方法是在子线程中执行的。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以看下这个问题的回答https://ask.csdn.net/questions/368793
  • 你也可以参考下这篇文章:Socket报connect reset异常
  • 除此之外, 这篇博客: Android实现TCP客户端中的 2.socket的连接 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    由于android平台的限制,与网络相关的操作只能在子线程中进行,所以这里我们单独建立一个线程用于socket的连接

     //子线程中进行网络相关操作
        class connectthread extends Thread {
    
            OutputStream outputStream=null;
            InputStream inputStream=null;
            @Override
            public void run() {
    
                //连接
                try {
                    socket=new Socket(a, b);
                    runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以
                    {
                        public void run()
                        {
                            // TODO Auto-generated method stub
                            Toast.makeText(MainActivity.this,"连接成功",Toast.LENGTH_SHORT).show();
    
                        }
                    });
                } catch (UnknownHostException e) {
                    // TODO Auto-generated catch block
                    runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以
                    {
                        public void run()
                        {
                            // TODO Auto-generated method stub
                            Toast.makeText(MainActivity.this,"连接失败",Toast.LENGTH_SHORT).show();
                        }
                    });
                    e.printStackTrace();
                }catch (IOException e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable()//不允许其他线程直接操作组件,用提供的此方法可以
                    {
                        public void run()
                        {
                            // TODO Auto-generated method stub
                            Toast.makeText(MainActivity.this,"连接失败",Toast.LENGTH_SHORT).show();
                        }
                    });
                }
    }
    

    socket=new socket(a,b)这一方法可以建立一个tcp连接,其中,a为ip地址,b为端口号
    如果连接成功,我们及通过Toast在屏幕中显示“连接成功”,若连接失败,则会转到异常中,我们通过Toast显示“连接失败”。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^