1文章来由:突然被问到会不会APP和PC进行通信,当时也是一脸懵逼,然后百度下,发现是用Socekt来进行通信的,没错,就是当初我们学java基础篇的时候做聊天的Socket。
2。下面就直接上demo,一个客户端和服务器通信的例子,具体安卓和pc通信的过程类似,因为没有测试,下次再进行上传。
a.首先写客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class TClient{
//服务端ip地址,这里用本地进行测试
private static final String IP_ADDR = "127.0.0.1";
private static final int PORT = 8099;//使用的端口号
private Socket chart;//建立一个Socket
private BufferedReader burf;//使用缓冲流来读从服务器返回的数据
private PrintWriter pw;//标准的String类型,向服务端发送数据
public void go() {
//使用while可以让本次连接一直进行,直到客户端判断手动结束线程,不然,本次通信只能进行一次,就会自动关闭。
while(true){
try {
chart = new Socket(IP_ADDR,PORT);//向服务端请求
//从socket中获取获取返回的流
burf = new BufferedReader(new InputStreamReader(chart.getInputStream(),"utf-8"));
//向socket写入输出流,true表示强行输出缓存
pw = new PrintWriter(new OutputStreamWriter(chart.getOutputStream(),"utf-8"),true);
//从键盘输入,给服务器发送数据
System.out.println("请输入: \t");
//读键盘输入的数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line_ = br.readLine();
//发送给服务器
pw.println(line_);
//pw.flush();(如果上面没有true,这里必须手动输出缓存)
//读取服务器文件
String line = burf.readLine();
System.out.println("服务器返回的数据"+line);
//关闭连接(返回的字符是end的时候,关闭本次连接)
try {
if ("end".equals(line)) {
System.out.println("客户端将关闭连接");
Thread.sleep(500);//让这个线程sleep
break; //跳出while循环,连接关闭
}
} catch (InterruptedException e) {
e.printStackTrace();
}
//关闭流
pw.close();
burf.close();
} catch (IOException e) {
System.out.println("无法连接服务器"+e.getMessage());
}finally{
//关闭流和Socket
try {
if(chart != null){
chart.close();
}
} catch (IOException e) {
System.out.println("客户端异常"+e.getMessage());
}
}
}
}
public static void main(String[] args){
System.out.println("客户端启动");
TClient tc = new TClient();
tc.go();
}
}
//客户端方面,(或者说APP方面),因为一般一个用户一个客户端,所以在客户端方面使用的是单一线程。
2.下面是重点方,服务器端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class T1Server{
private static final int PORT = 8099;//与客户端相同的端口
public void go(){
try {
ServerSocket sot = new ServerSocket(PORT);//让服务器监听来自改端口的客户的请求
while(true){
Socket client = sot.accept();//服务器创建一个新的Socket与客服端进行通信
new DealSockets(client);//一个新的线程处理这次通信
}
} catch (IOException e) {
System.out.println("服务器监听客户端失败"+e.getMessage());
}
}
public static void main(String[] args) {
System.out.println("服务端启动");
T1Server ts = new T1Server();
ts.go();
}
}
//建立一个新的线程处理通信
class DealSockets implements Runnable{
private Socket client;
private BufferedReader bufr;
private PrintWriter bufw;
public DealSockets(Socket client){
this.client = client;
new Thread(this).start();
}
public void run() {
try {
//读取客户端返回的数据
bufr = new BufferedReader(new InputStreamReader(client.getInputStream(),"utf-8"));
String line_ = bufr.readLine();
System.out.println("客户端发送的数据"+line_);
//向客户端发送数据(这里写死了,可以用流从键盘输入,和客户端的一样)
bufw = new PrintWriter(new OutputStreamWriter(client.getOutputStream(),"utf-8"));
bufw.println("ends");
//在使用bufw后直接调用close();,也可以直接把缓存写出去
//关闭流
bufw.close();
bufr.close();
} catch (IOException e) {
System.out.println("客户端输入流异常:"+e.getMessage());
}finally{
try {
if(client != null){
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端处理的时候,(默认的是多个用户同时要使用服务器),所以加上了while循环,可以让多个用户进入,一直监听客户端,后面处理通信用了一个新的线程,是为了让用户可以同时和服务端通信,不然的情况就(不使用多线程)是一个用户使用完本次连接,第二个用户才能进入。这样就会出现问题了。
3.这个demo很简陋,具体实际应用还要看业务需求,比如我这个通讯,写死了是客户端发消息,服务器才能返回消息,然后服务器在发送消息。真正在写聊天的时候,客户端需要一个新的线程专门从socket中读取服务器的消息来进行显示。这样实用性就会高一点了。
4.如有不当的地方,敬请指正。