安卓客户端/笔记本电脑服务器



我正在尝试创建一个客户端/服务器应用程序,其中笔记本电脑充当服务器并与充当客户端的Android手机共享其互联网连接,我可以建立客户端和服务器之间的连接,问题是当客户端尝试在套接字上写入时,它会卡在那里。 这是安卓的 xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.giuseppe.client">
<uses-permission android:name="android.permission.INTERNET" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
</uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

这是安卓客户端

package com.example.giuseppe.client;
import java.io.*;
import java.net.*;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import org.w3c.dom.Text;
import static java.net.InetAddress.*;
public class MainActivity extends Activity {
private Socket socket;
private static final int port=5555;
private static final String addr="192.168.1.37";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Client()).start();
}
public void onClick(View view){
try{
TextView tx=(TextView) findViewById(R.id.txt);
EditText et= (EditText) findViewById(R.id.et);
String str= et.getText().toString();
DataOutputStream out= new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())) ;
out.writeUTF(str);
out.close();
socket.close();
}catch(UnknownHostException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
}
class Client implements Runnable {
@Override
public void run() {
try {
TextView tx= (TextView) findViewById(R.id.txt);
tx.setText("Before connection");
InetAddress server = InetAddress.getByName(addr);
socket = new Socket("192.168.1.37", port);
tx.setText("After connection");
} catch (UnknownHostException a) {
} catch (IOException a) {
} catch (Exception a){
}
}
}

这是服务器代码

import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) {
int port=5555;
byte[] buff =new byte[1024];
String str; 
// TODO Auto-generated method stub
try {
ServerSocket server=new ServerSocket(port);
System.out.println("Before accept");
Socket client=server.accept(); 
System.out.println("After accept");
DataInputStream in=new DataInputStream(new BufferedInputStream(client.getInputStream()));
str=in.readUTF();

System.out.println("Message received");
in.close();
client.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} 
}
}

我想问题出在客户端上,因为我也尝试使用服务器发送字符串,当服务器发送字符串时,客户端没有收到它。 对不起,我的英语不好。感谢大家

+++++编辑+++++

我也尝试了 OutputStream out=socket.getOutputStream(); 然后是 out.write(str.getBytes()),但在这种情况下,当我尝试在套接字中写入时,它卡在这里,可能是任何 android 的配置问题?

免责声明:我无法验证您的Android代码的正确性,所以我假设这很好,并且只评论您的网络代码,这是您问题的根本原因。

代码中的 2 个主要问题是:

  1. 在服务器代码中,您正在读取和读取,并且什么都不做
  2. 您的服务器是单线程的

您的主要问题是上面的#1,一旦解决#1,您就会遇到另一个问题#2。

您的#1问题是您需要定义一些有关如何考虑流或输入结束的逻辑,请参阅下面的代码示例(阅读代码中的注释),也不一定需要使用readUTF方法,而是可以使用">I/O桥接类",例如InputStreamReader它充当字节流和字符流之间的桥梁,所以你可以使用InputStreamReader clientSocketReader = (new InputStreamReader(clientSocket.getInputStream(), "UTF8"));,我不能说为什么你真的需要DataInputStream并且不能使用InputStreamReader但在我看来你可以使用桥类。

int portNumber = 8001;
try {
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) { // **** this basically means that read one full line, you have to specify condition like this, so suppose you have created a telnet session with this server now keep on typing and as soon you will hit entered then while block processing will start. 
System.out.println("@@@ " + inputLine);
out.println(inputLine); // *** here same input is written back to the client, so suppose you have telnet session then same input can be seen
}
} catch (IOException e) {
System.out.println(
"Exception caught when trying to listen on port " + portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}

现在你的#2问题是你的服务器是单线程的,你需要有一个多线程服务器,这基本上意味着你应该在新线程中处理每个客户端请求。阅读我的这个答案,它对单线程 v/s 多线程服务器提供了更多了解。请参阅以下多线程服务器的代码示例:

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import com.learn.Person;
/**
* @author himanshu.agrawal
*
*/
public class TestWebServer2 {
public static void main(String[] args) throws IOException {
startWebServer();
}
/**
* test "backlog" in ServerSocket constructor
test -- If <i>bindAddr</i> is null, it will default accepting
* connections on any/all local addresses.
* @throws IOException
*/
private static void startWebServer() throws IOException {
InetAddress address = InetAddress.getByName("localhost");
ServerSocket serverSocket = new ServerSocket(8001, 1, address);
// if set it to 1000 (1 sec.) then after 1 second porgram will exit with SocketTimeoutException because server socket will only listen for 1 second.
// 0 means infinite
serverSocket.setSoTimeout(/*1*/0000);
while(true){
/*Socket clientSocket = serverSocket.accept();*/ // a "blocking" call which waits until a connection is requested
System.out.println("1");
TestWebServer2.SocketThread socketThread = new TestWebServer2().new SocketThread();
try {
socketThread.setClientSocket(serverSocket.accept());
Thread thread = new Thread(socketThread);
thread.start();
System.out.println("2");
} catch (SocketTimeoutException socketTimeoutException) {
System.err.println(socketTimeoutException);
}
}
}
public class SocketThread implements Runnable{
Socket clientSocket;
public void setClientSocket(Socket clientSocket) throws SocketException {
this.clientSocket = clientSocket;
//this.clientSocket.setSoTimeout(2000); // this will set timeout for reading from client socket.
}
public void run(){
System.out.println("####### New client session started." + clientSocket.hashCode() + " | clientSocket.getLocalPort(): " + clientSocket.getLocalPort()
+ " | clientSocket.getPort(): " + clientSocket.getPort());
try {
listenToSocket(); // create this method and you implement what you want to do with the connection.
} catch (IOException e) {
System.err.println("#### EXCEPTION.");
e.printStackTrace();
}
}

}
}

这是一个艺术生产者/消费者的问题。服务器从接受返回后,客户端与服务器建立了连接。 当服务器等待数据读取时(消费者),客户端(生产者)什么都不做。客户端应该在套接字上写一些东西才能继续。

最新更新