我试图创建一个控制客户端和服务器之间套接字连接的服务,以保持客户端活动之间的套接字连接。该客户端的过程是当用户点击连接按钮,将创建套接字并且客户端将移动到下一个活动时,在此活动中我创建了一个按钮,使用新创建的数据将数据发送到服务器插座。但是,单击此按钮时,服务器似乎没有从客户端接收任何数据。 这是我的服务
//ConnectionService.java
public class ConnectionService extends Service {
...
public class LocalBinder extends Binder {
public ConnectionService getService(){
return ConnectionService.this;
}
}
private final IBinder myBinder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
@Override
public void onCreate(){
super.onCreate();
Log.i("Socket connection","I am on onCreate()");
}
public void isBoundable(){
Toast.makeText(this, "Boundable", Toast.LENGTH_LONG).show();
}
public void getSocketInfo(){
Log.i("Socket info",socket.toString());
}
public void sendMessage(String message){
if(dos!=null){
Log.i("Data_Transfer","Sending message");
try {
dos.writeUTF(message);
dos.flush();
}catch (IOException e){
e.printStackTrace();
}
Log.i("Data_Transfer","Message sent");
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
super.onStartCommand(intent,flags,startId);
//Log.i("Socket connection","I am in onStartCommand");
Runnable connection = new SocketConnection();
new Thread(connection).start();
return START_STICKY;
}
class SocketConnection implements Runnable{
@Override
public void run(){
//create socket connection
try {
//Log.i("Socket connection", "C: connecting");
serverAddress = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddress, SERVER_PORT);
//Log.i("Socket connection", "C: connected");
dos = new DataOutputStream(socket.getOutputStream());
Log.i("TCP client","C: sent");
dos.writeUTF("Message from client");
dos.flush();
dis = new DataInputStream(socket.getInputStream());
String msg = "";
msg=dis.readUTF();
Log.d("response",msg);
} catch (IOException e){
Log.e("TCP client","Cannot connect to server");
}
}
}
活动创建了服务:
private ConnectionService boundService;
private Boolean isBound;
private ServiceConnection connection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service){
Log.i("Connect","Creating service");
boundService = ((ConnectionService.LocalBinder)service).getService();
if(boundService!=null){
Log.i("Connect","service bounded");
boundService.isBoundable();
responseFromServerView.setText("Connected");
}
}
@Override
public void onServiceDisconnected(ComponentName name){
boundService = null;
}
};
private void doBindService(){
bindService(new Intent(ShareImages.this,ConnectionService.class),connection, Context.BIND_AUTO_CREATE);
isBound = true;
}
private void doUnbindService(){
if(isBound){
unbindService(connection);
isBound = false;
}
}
@Override
protected void onDestroy(){
super.onDestroy();
doUnbindService();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.share_images);
responseFromServerView = (TextView)findViewById(R.id.responseFromServer);
responseFromServerView.setText("Connecting");
sendDataBtn = (Button)findViewById(R.id.sendDataBtn);
sendDataBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(boundService!=null){
boundService.getSocketInfo();
boundService.sendMessage("New message");
Log.i("Connect","Sent");
}
Toast.makeText(ShareImages.this, "Sent to server", Toast.LENGTH_SHORT).show();
}
});
startService(new Intent(ShareImages.this, ConnectionService.class));
doBindService();
}
服务器代码:
private class SocketServerThread implements Runnable {
static final int SocketServerPORT = 8080;
int count = 0;
@Override
public void run() {
Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
try {
serverSocket = new ServerSocket(SocketServerPORT);
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
info.setText("I'm waiting here: "
+ serverSocket.getLocalPort());
}
});
while (true) {
socket = serverSocket.accept();
dataOutputStream = new DataOutputStream(
socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
String messageFromClient = "";
//If no message sent from client, this code will block the program
messageFromClient = dataInputStream.readUTF();
count++;
message += "#" + count + " from " + socket.getInetAddress()
+ ":" + socket.getPort() + "\n"
+ "Msg from client: " + messageFromClient + "\n";
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
msg.setText(message);
}
});
String msgReply = "Hello from Android, you are #" + count;
dataOutputStream.writeUTF(msgReply);
System.out.println(messageFromClient);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
final String errMsg = e.toString();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
msg.setText(errMsg);
}
});
}
当"连接到服务器"按下,客户端发送消息"来自客户端的消息"到服务器,它的工作原理,服务器可以收到此消息。但是在连接之后,在新活动中,按另一个按钮发送"新消息"字符串到服务器不起作用,服务器没有收到消息,即使boundService仍然存在。有人请帮我解决这个问题。 P / S:这是使服务器处理多个客户端和需要始终保持套接字连接的客户端的正确方法吗?
答案 0 :(得分:1)
您的服务器实施不正确。接受连接后,您的服务器应该生成一个新线程并将accept返回的套接字传递给它。然后,该线程应根据需要与客户端通信。 您当前的实现接受连接,从客户端读取第一条消息,然后循环返回“接受”。
答案 1 :(得分:0)
这只是猜测。但我怀疑您的服务与您的活动运行的过程相同(如果不是,可能无关紧要。)
因此,当通过onClick侦听器调用此代码时:
public void sendMessage(String message){
if(dos!=null){
Log.i("Data_Transfer","Sending message");
try {
dos.writeUTF(message);
dos.flush();
}catch (IOException e){
e.printStackTrace();
}
Log.i("Data_Transfer","Message sent");
}
}
dos.write
调用抛出IOException,因为您试图在UI线程上执行阻塞网络调用。