android 教程 服务器 androidstudio服务器
原理很简单,相信大家对 socket 编程都有了解
之前写的与现在的区别就是,之前服务端是在本地运行,在同一局域网才能通信,现在服务端是在轻量应用服务器上运行,不同网络都能通信(前提是你的轻量应用服务器允许不同网络访问)
1.没购买的,先购买,至于买什么价位的,如何选择镜像,地域、套餐,时长等我不是很专业,你们可以找几篇专业的文章来研究,我这里是以Tomcat 8 为例
2.购买好后
3.
4.
5.
6.
7.添加端口号,3389是Windows远程连接端口号,5000是允许外网访问的端口
8.先来看一下服务端代码
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Server { private static final int PORT = 5000; private List<Socket> mList = new ArrayList<Socket>(); private ServerSocket server = null; private ExecutorService myExecutorService = null; public static void main(String[] args) { new Server(); } public Server() { try { server = new ServerSocket(PORT); myExecutorService = Executors.newCachedThreadPool(); System.out.println("服务端运行中...\n"); Socket client = null; while(true) { client = server.accept(); mList.add(client); myExecutorService.execute(new Service(client)); } }catch(Exception e){e.printStackTrace();} } class Service implements Runnable { private Socket socket; private BufferedReader in = null; private String msg = ""; public Service(Socket socket) { this.socket = socket; try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); msg = "用户:" +this.socket.getInetAddress() + "~加入了聊天室" +"当前在线人数:" +mList.size(); this.sendmsg(); }catch(IOException e){e.printStackTrace();} } @Override public void run() { try{ while(true) { if((msg = in.readLine()) != null) { if(msg.equals("bye")) { System.out.println("~~~~~~~~~~~~~"); mList.remove(socket); in.close(); msg = "用户:" + socket.getInetAddress() + "退出:" +"当前在线人数:"+mList.size(); socket.close(); this.sendmsg(); break; }else{ msg = socket.getInetAddress() + " 说: " + msg; this.sendmsg(); } } } }catch(Exception e){e.printStackTrace();} } public void sendmsg() { System.out.println(msg); int num = mList.size(); for(int index = 0;index < num;index++) { Socket mSocket = mList.get(index); PrintWriter pout = null; try { pout = new PrintWriter(new BufferedWriter( new OutputStreamWriter(mSocket.getOutputStream(),"UTF-8")),true); pout.println(msg); }catch (IOException e) {e.printStackTrace();} } } } }9.在桌面新建一个txt,后缀改为java,然后把服务端代码放到里面,我这里只有一个java类,没有其他文件,所以可以打包成.java文件放到服务器上运行,如果你的服务端代码有很多,那么你可以将其打包成.jar,然后放到服务器上运行
10.将Server.java 传到我的轻量应用服务器上,这里有的唠一唠了。
xshell 和 xftp 官网链接,进入官网后,点击 XSHELL 和 XFTP 进行下载
11.选择家庭和学校用户,获取免费下载链接
12.
13.
14.
15.重复12.13.14步骤再下载Xftp,当然如果你已经下载好了就忽略这一步
16.我这是下载在桌面了,双击安装
17.
18.
19.
20.
21.
22.Xftp的安装和Xshell 类似,一直点下一步即可,我就不赘述了
23.Xshell 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xftp是一个软件应用程序,可以帮助您通过网络传输文件。
这里先讲一下Xshell的使用
24.公网IP在哪呢?如下
25.用户名和密码在哪呢?如下
26.
27.连接成功,就可以对服务器终端进行操作了
28.Xftp的使用,双击Xftp启动
29.如果Xftp不弹出传输窗口,你也可以像Xshell那样新建会话,连接你的服务器
30.可以开始将本地文件传输到你的远程服务器上了(我这乱涂乱画并不是我心情不好或什么的哈,哈哈)
31.找到我们之前打包好的那个Server.java文件(不会忘了吧,往上再看看)
32.
33.传输成功后,就是在服务器上运行起来,打开Xshell(当然你也可以在浏览器打开你的远程连接,如下图所示,这里我还是在Xshell执行)
34.服务端代码已经运行起来了,接下来就是客户端代码了
项目结构
MainActivity代码如下,注意公网IP填写你自己的
package com.example.myappserver2; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; public class MainActivity extends AppCompatActivity{ //定义相关变量,完成初始化 private TextView txtshow; private EditText editsend; private Button btnsend; private static final String HOST = "x.x.x.x"; //这里填写你的公网IP private static final int PORT = 5000; //这里是你之前填写的外网访问端口号 private Socket socket = null; private BufferedReader in = null; private PrintWriter out = null; private String content = ""; private StringBuilder sb = null; private String msg; private String result; //定义一个handler对象,用来刷新界面 public Handler handler2 = new Handler() { public void handleMessage(Message msg) { if (msg.what == 0x123) { sb.append(content); txtshow.setText(sb.toString()); } } }; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_main); sb = new StringBuilder(); txtshow = (TextView) findViewById(R.id.txtshow); editsend = (EditText) findViewById(R.id.editsend); btnsend = (Button) findViewById(R.id.btnsend); final LooperThread looperThread = new LooperThread(); looperThread.start(); btnsend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Message message = Message.obtain(); String msg = editsend.getText().toString(); message.obj = msg; looperThread.handler.sendMessage(message); new Thread() { //覆写Run方法 @Override public void run() { try { while (true) { if (socket.isConnected()) { if (!socket.isInputShutdown()) { if ((content = in.readLine()) != null) { content += "\n"; handler2.sendEmptyMessage(0x123); } } } } } catch (Exception e) { e.printStackTrace(); } } }.start(); } }); } class LooperThread extends Thread { public Handler handler; @Override public void run() { super.run(); try { socket = new Socket(HOST, PORT); in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); Log.i("TAG0", "run0: "+socket.getInetAddress()); Log.i("TAG", "run: "+in.readLine()); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())), true); } catch (IOException e) { e.printStackTrace(); } Looper.prepare(); handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); out.println(msg.obj); } }; Looper.loop();//loop()会调用到handler的handleMessage(Message msg)方法,所以,写在下面; } } }activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="小猪简易聊天室" /> <TextView android:id="@+id/txtshow" android:layout_width="match_parent" android:layout_height="wrap_content" /> <EditText android:id="@+id/editsend" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btnsend" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送" /> </LinearLayout>AndroidManifest.xml里加上这条权限
<uses-permission android:name="android.permission.INTERNET"/>35.运行一下,看我运行结果,这里需要前台实时查看nohub.out文件内容,用这个命令
tail -f nohup.out
Android Studio和轻量应用服务器实现 socke
36.
这里还要说一下,nohup java Server & 是让Server在后台一直运行,那么怎么停止呢?再来看看这张密密麻麻的图片吧,当我执行 nohup java Server & 后是不是输出了一个 [1] 4765 细心的人都能看见
37.当然你忘记了也没关系,我这里只是为了告诉你有这么一回事,你可以输入命令:
ps -aux | grep java(加上grep java,表示过滤带java的程序)# 查看所有进程的命令。
通过以上方法,我们已经知道了Server.java的编号为4765,所以通过以下命令就可以让其停止
kill pid # pid是ps命令查看到的进程编号
这里我们查到Server.java 进程的编号为4765
kill 4765
执行kill 4765后,再通过 ps -aux | grep java 查询发现,Server.java 已经被杀死了
到此,这篇文章就写完了。希望能帮助到大家,如果有错,欢迎指正,我必及时更改。