浅谈Socket通信

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.如有不当的地方,敬请指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值