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,因为该方法是在子线程中执行的。
不知道你这个问题是否已经解决, 如果还没有解决的话:由于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显示“连接失败”。