Android开发Android开发Android开发经验谈

Android网络 | Socket(Eclipse--Java

2019-12-05  本文已影响0人  凌川江雪

Socket基础

TCP/IP协议基础

UDP协议

TCP、UDP选择的决定因素

基于Socket的Java网络编程

1.Socket通信的过程
2.创建Socket
    Socket client = new Socket("127.0.0.1", 80);
    ServerSocket server = new ServerSocket(80);
  • 注意:
    必须小心地选择端口
    每一个端口提供一种特定的服务
    只有给出正确的端口,才能获得相应的服务

    0~1023端口号系统所保留
    例如
    HTTP服务的端口号为80,
    Telnet服务的端口号为21,
    FTP服务的端口号为23
    所以我们在选择端口号时,最好选择一个大于1023以防止发生冲突
    另外,
    创建Socket时如果发生错误,将产生IOException
    程序中必须对之做出处理
    所以在创建SocketServerSocket时必须捕获抛出异常

TCP编程详解

使用ServerSocket

在Java程序中,

    //创建一个ServerSocket,用于监听客户端Socket的连接请求
    ServerSocket ss = new ServerSocket(30000);
    //采用循环不断接受来自客户端的请求
    while (true)
    {
    //每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
    Socket s = ss.accept();
    //下面就可以使用Socket进行通信了
    ...
    }
使用Socket
    //创建连接到本机、30000端口的Socket
    Socket s = new Socket("127.0.0.1" , 30000);
public class Server
{
    public static void main(String[] args)
        throws IOException
    {
        //创建一个ServerSocket,用于监听客户端Socket的连接请求
        ServerSocket myss = new ServerSocket(30001);
        //采用循环不断接受来自客户端的请求
        while (true)
        {
          //每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
          Socket s = myss.accept();
          //将Socket对应的输出流包装成PrintStream
          PrintStream ps = new PrintStream(s.getOutputStream());
          //进行普通IO操作
          ps.println("凌川江雪!");
          ps.println("望川霄云!");
          ps.println("万年太久,只争朝夕!");
          ps.println("人间正道是沧桑!");
          ps.println("穷善其身,达济天下!");
          
          //关闭输出流,关闭Socket
          ps.close();
          s.close();
        }
    }
}
public class Client {

    public static void main(String[] args)  throws IOException
    {
        Socket socket = new Socket("127.0.0.1" , 30001);
        //将Socket对应的输入流包装成BufferedReader
        BufferedReader br = new BufferedReader(
          new InputStreamReader(socket.getInputStream()));
        
        //进行普通IO操作         
        StringBuilder response = new StringBuilder();
        String line;
        
        //一行一行地读取并加进stringbuilder
        while((line = br.readLine()) != null){
            response.append(line + "\n");
        }
        
        System.out.println("来自服务器的数据:" + "\n" + response.toString());  
        
        //关闭输入流、Socket
        br.close();
        socket.close();
    }

}




TCP中的多线程

1/4 接下来介绍具体实现流程,首先看下面的IServerClass:

public class IServer
{
    //定义保存所有Socket的ArrayList
    public static ArrayList<Socket> socketList = new ArrayList<Socket>();

    public static void main(String[] args) 
        throws IOException
    {
        ServerSocket ss = new ServerSocket(30000);
        while(true)
        {
            //此行代码会阻塞,将一直等待别人的连接
            Socket s = ss.accept();
            socketList.add(s);
            //每当客户端连接后启动一条ServerThread线程为该客户端服务
            new Thread(new Serverxian(s)).start();
        }
    }
}

IServer类中,
服务器端(ServerSocket )只负责接受客户端Socket连接请求
每当客户端Socket连接到该ServerSocket之后,
程序将客户端对应的Socket(客户Socket的对面一端)加入 socketList集合保存
并为该Socket启动一条线程Serverxian),
线程负责处理 该Socket所有 的 通信任务
小结:
IServer类完成的业务是:
1.接收客户端Socket
2.保存对应返回的Socket
3.启动处理线程

2/4 接着看服务器端线程类文件:

package liao.server;
import java.io.*;
import java.net.*;
import java.util.*;

//负责处理每个线程通信的线程类
public class Serverxian implements Runnable 
{
    //定义当前线程所处理的Socket
    Socket s = null;
    
    //该线程所处理的Socket所对应的输入流读取器
    BufferedReader br = null;
    
    public Serverxian(Socket s)
        throws IOException
    {
        this.s = s;
        //初始化该Socket对应的输入流
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
    }
    
    public void run()
    {
        try
        {
            String content = null;
            
            //采用循环不断从Socket中读取客户端发送过来的数据
            while ((content = readFromClient()) != null)
            {
                
                //遍历socketList中的每个Socket,
                //将读到的内容向每个Socket发送一次
                for (Socket s : IServer.socketList)
                {
                     //将Socket对应的输出流包装成PrintStream
                    PrintStream ps = new PrintStream(s.getOutputStream());
                    ps.println(content);
                }
            }
        }
        catch (IOException e)
        {
            //e.printStackTrace();
        }
    }
    
    //定义读取客户端数据的方法
    private String readFromClient()
    {
        try
        {
            return br.readLine();   
        }
        //如果捕捉到异常,表明该Socket对应的客户端已经关闭
        catch (IOException e)
        {
            //删除该Socket。
            IServer.socketList.remove(s);
        }
        return null;
    }
}

Serverxian类(服务器端线程类)中,
注意是线程类,继承Runnable,重写run方法
会不断读取客户端数据,

在获取时使用方法readFromClient()来读取客户端数据。
如果读取数据过程中捕获到 IOException异常,
则说明此Socket对应的客户端Socket出现了问题,
程序就会将此Socket从socketList中删除。

当服务器线程读到客户端数据之后会遍历整个socketList集合,
并将该数据向socketList集合中的每个Socket发送一次,
该服务器线程将把从Socket中读到的数据
向socketList中的每个Socket转发一次。

上一篇下一篇

猜你喜欢

热点阅读