本文共 7674 字,大约阅读时间需要 25 分钟。
IP地址为你的服务器公网IP地址,端口号为已开放的端口号,如果用的是阿里云,需要设置端口号,否则无法进行连接。端口号设置示例如下:
package socket;import java.io.*;import java.net.ServerSocket;import java.net.Socket;/** * @author :hly * @github :github.com/SiriusHly * @blog :blog.csdn.net/Sirius_hly * @date :2018/8/19 */public class Server implements Runnable { public static final String IP = "123.XX.219.XX"; public static final int PORT = 5000; @Override public void run() { ServerSocket serverSocket = null; try { //绑定端口 serverSocket = new ServerSocket(PORT); System.out.println("等待连接"); Socket socket = serverSocket.accept(); System.out.println("连接成功"); //获取输入流 //BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); DataInputStream in = new DataInputStream(socket.getInputStream()); //获取输出流 //BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); DataOutputStream out = new DataOutputStream(socket.getOutputStream()); //读取信息 System.out.println("读取1"); String str = in.readUTF(); System.out.println("读取2"); System.out.println("服务器接收到的消息为:"+str); //发送信息给客户端 out.writeUTF("1"); out.flush(); socket.close(); } catch (IOException e) { e.printStackTrace(); } finally { if (serverSocket!=null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String[] args) { Thread myThread = new Thread(new Server()); myThread.start(); }}
如果传输单条数据,输入流可能无法使得可以接收到数据,代码如下:
//BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));String str = in.readLine()
上面的代码接收不到数据,因为in.readLine是一个阻塞方法,只要没有断开连接,就会一直进行等待,而不是返回null,当断开连接后,就会出现异常,通常需要用一定的分隔符,socket适用麻烦,下面是其源码:
String readLine(boolean ignoreLF) throws IOException { StringBuffer s = null; int startChar; synchronized (lock) { ensureOpen(); boolean omitLF = ignoreLF || skipLF; bufferLoop: for (;;) { if (nextChar >= nChars) fill(); //在此读数据 if (nextChar >= nChars) { /* EOF */ if (s != null && s.length() > 0) return s.toString(); else return null; } ......//其它 } private void fill() throws IOException { ..../其它 int n; do { n = in.read(cb, dst, cb.length - dst); //实质 } while (n == 0); if (n > 0) { nChars = dst + n; nextChar = dst; } }
客户端为安卓客户端,在进行网络连接时,需要在配置文件AndroidManifest.xml里面加上对网络访问的允许,代码如下:
这里是显示部分的代码,完整代码就不给出了,可以在笔者的github:里面下载:
页面截图:
对一些事件进行监听
package com.example.hly.app.activity;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.ProgressBar;import android.widget.Toast;import com.example.hly.app.R;import com.example.hly.app.thread.LoginThread;public class MainActivity extends AppCompatActivity { private Button btnLogin; private EditText txtUserId; private EditText txtUserPassword; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnLogin = (Button)findViewById(R.id.btnLogin); txtUserId = (EditText)findViewById(R.id.userId); txtUserPassword =(EditText)findViewById(R.id.userPassword); progressBar = (ProgressBar)findViewById(R.id.progressBar); //progressBar.setVisibility(View.GONE); //登录事件监听 btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //progressBar.setVisibility(View.VISIBLE); try { LoginThread loginThread = new LoginThread(txtUserId.getText().toString(),txtUserPassword.getText().toString()); Thread t = new Thread(loginThread); t.start(); t.join(); //progressBar.setVisibility(View.GONE); } catch (InterruptedException e) { e.printStackTrace(); } if(LoginThread.message.equals("1")) { Toast.makeText(getApplicationContext(), "登录成功", Toast.LENGTH_SHORT); Intent intent = new Intent(); intent.setClass(MainActivity.this, Index.class); MainActivity.this.startActivityForResult(intent, 1); }else{ Toast.makeText(getApplicationContext(), "登录失败", Toast.LENGTH_SHORT); } } }); }}
package com.example.hly.app.thread;import android.util.Log;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.Socket;/** * Created by hly on 2018/8/19. */public class LoginThread implements Runnable { private String userId ; private String userPassword ; public static String message =" "; public static final String IP = "123.xx.xx.xx"; public static final int PORT = 5000; public LoginThread() { } public LoginThread(String userId, String userPassword) { this.userId = userId; this.userPassword = userPassword; } @Override public void run() { try { Log.e("开始连接","Start"); Socket socket = new Socket(IP,PORT); Log.e("成功连接","success"); //获取输入流 //BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); DataInputStream in = new DataInputStream(socket.getInputStream()); //获取输出流 //BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); DataOutputStream out = new DataOutputStream(socket.getOutputStream()); out.writeUTF(userId+" "+userPassword); //刷新发送 out.flush(); message = in.readUTF(); System.out.print("接收的数据为:"+in.readUTF()); socket.close(); } catch (IOException e) { e.printStackTrace(); } }}
1.首先为了方便部署,需要把服务端代码打包成jar包,在IDEA上是这样打包的:
file->preject Constructure,接着,步骤如下图:
2.接着会出现以下选项,选择extract to the target JAR打包的是一个jar包,第二个是带上你项目的所有jar包,一般选择第一个,选择第二个可能会出现无法加载主类。详情:
3.在这里,可以选择需要添加的JAR包,不需要可以不用填,完成后点击ok
4.然后我们在IDEA上方找到build,进行以下操作进行了
5.之后可以在这个路径下找到jar包
得到jar包之后,双击如果不能运行和连接,一般来说可以连接可以使用命令执行,如下:java -jar +你的jar包,之后程序运行。
如果不能双加运行,打开注册表
依次知道到HKEY_CLASS_ROOT->Applications->javaw.exe修改默认值即可
如果你行通过直接点击来运行而不需要每一次都很麻烦输入命令,教你一个技巧,新建文本文档,修改后缀名为bat
然后加入以下格式.
D:
cd WEBPRODUCTION\App\out\artifacts\App_jar java -jar App.jar pauseD: //代表去D盘
cd //代表进入目录
接下来执行jar
pause让cmd停止
运行效果图:
如果只有一个java文件的话,可以直接cmd跳转到该文件目录,然后输入命令javac Server.java(文件名),之后会产生一个Class后缀文件,在输入命令java Server 便能运行,注意java文件里面不能出现包名,不然会出现无法加载主类。