Socket编程基础--基于TCP协议的网络编程

来源:互联网 发布:java api在线 编辑:程序博客网 时间:2024/06/05 05:16

一、概述

在学习TCP协议之前,需要了解网络编程中的几个基本概念。

  • IP协议:是Internet Protocol的外语缩写,为计算机网络相互连接进行通信而设计的协议。在因特网中,它是能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。任何厂家生产的计算机系统,只要遵守IP协议就可以与因特网互连互通。IP地址具有唯一性。
  • TCP协议:TCP协议被称作是一种端对端协议。它提供IP环境下的数据可靠传输,提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的数据包发送。通俗说,它是事先为所发送的数据开辟出连接好的通道,然后再进行数据发送
  • 端口号Port:主要是计算机用来来区分连接不同应用程序。注意:0-1023不可以使用,系统已经占用。

二、Java的基本网络支持

  • 使用InetAddress
  • URLDecoder和URLEncoder
  • URL、URLConnetction(这个后面说)

    InetAddress的简单使用

 public static void main(String[] args) throws Exception {        InetAddress ia = InetAddress.getLocalHost() ;        System.out.println("ip:" + ia.getHostAddress());        System.out.println("主机名:" + ia.getHostName());    }

URLDecoder和URLEncoder

URLDecoder和URLEncoder是完成字符串和application/x-www-form-urlencode MIME字符串之间的相互转化

  • URLDecoder的decode()方法可以将一个看上去是乱码的转换成不是乱码的字符串
  • URLEncoder的encode()方法可以将一个看上去不是乱码的转换成是application/x-www-form-urlencode MIME的字符串
public static void main(String[] args) throws Exception {        String keyword = URLEncoder.encode("李文");        System.out.println(keyword);        keyword = URLDecoder.decode(keyword) ;        System.out.println(keyword);    }

三、通信流程

服务端

计算机能够接受通信实体请求的类是ServerSocket,ServerSocket用来监听客户端对应的socket,一般我们在while(true)里使用ServerSocket不断的获取socket,如果没用连接它会处于等待状态。

常用api:

  • accept():获取一个客户端socket的连接请求,这个方法会返回一个与客户端对应的socket,否则会处于等待状态,线程阻塞。
  • ServerSocket(int port):用指定端口号创建一个ServerSocket该值可以在0-65535之间。上面已经提过,0-1023不要用。
  • ServerSocket(int port,int backlog):增加一个改变连接队列长度的参数。
 //1.创建socketserver,监听3000端口        ServerSocket ss = new ServerSocket(30000) ;        while(true){            Socket s = ss.accept();            //2.将输出流包装成PrintStream            PrintStream ps = new PrintStream(s.getOutputStream()) ;            //3.进行IO操作            ps.println("hello socket,i am from SocketServer");            //4.关流            ps.close();             s.close() ;        }

客户端

客户端通常使用Socket的构造器连接指定服务器
构造函数如下:
public Socket(String host, int port)
使用如下:

//1.创建socket        Socket s = new Socket("127.0.0.1",30000) ;        BufferedReader br = new BufferedReader(new      InputStreamReader(s.getInputStream())) ;        String line = br.readLine();        System.out.println("来自服务端:" + line );        s.close() ;

上面的127.0.0.1是连接本地IP的。大家可以到C:\Windows\System32\drivers\etc这个目录下的host文件中查看到。
上面程序运首先要运行服务端,然后在运行客户端就可以进行通信了。
当服务端、客户端连接到了对应的socket之后,程序就不用再区分服务端、客户端了,两者是通过各自的socket通信。socket通过如下两个api来获取输出流、输入流。

 public InputStream getInputStream() public OutputStream getOutputStream() 

四、加入多线程

上面的client、server只是简单的通信,下面实现一个包含多线程的socket通信。我们在服务端创建多线程线程,每一个socket对应一个线程,这个线程负责读取socket输入流中的内容,也就是从客户端发送过来的数据,然后再返回给客户端信息表示收到了。

服务端代码:

    public static ArrayList<Socket> socketList = new ArrayList<Socket>() ;    public static void main(String[] args) throws Exception {        ServerSocket ss = new ServerSocket(30001) ;        while(true){            Socket s = ss.accept() ;            //每次获取一个socket,添加到集合中            socketList.add(s) ;            //开启线程执行任务            new Thread(new ServerThread(s)).start();        }    }

服务端创建一个集合用来存放来自客户端的Socket,每当获取一个socket,就开始启动一个线程,该线程用来处理通信业务。

class ServerThread implements Runnable{    //处理的socket    Socket s = null ;    //处理socket对应的流    BufferedReader br = null ;    public ServerThread(Socket s ) throws IOException{        this.s = s ;        br = new BufferedReader(new InputStreamReader(s.getInputStream())) ;    }    public void run() {        String context ;        while((context=readFromClient())!= null ){            for (Socket s : MyServer.socketList) {                System.out.println("服务端收到数据了:" + context );                PrintStream ps;                try {                    ps = new PrintStream(s.getOutputStream());                    ps.println(context + "---来自服务端");                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    public String readFromClient(){        try {            return br.readLine();        } catch (IOException e) {            e.printStackTrace();            //删除socket            MyServer.socketList.remove(s);        }         return null ;    }}

客户端代码:

public static void main(String[] args) {        //1.创建socket        try {            Socket s = new Socket("127.0.0.1",30001) ;            //2.获取来自服务端的数据            new Thread(new ClientThread(s)).start() ;            //3.获取socket对应的输出流            PrintStream ps = new PrintStream(s.getOutputStream()) ;            String line = null ;            //4.键盘输入            BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;            while((line = br.readLine())!= null ){                //5.将键盘输入写到socket输出流中                ps.println(line);            }        } catch (Exception e) {            e.printStackTrace();        }    }

重要的地方已经注释,代码不同,相信能看懂。这样就完成了多线程的通信了,还是和上面一样,先运行server,再运行client,通过运行可以知道每个客户端可以看到其它客户端的信息。

Ok,这篇已经结束了,这篇只是简单介绍了Socket的基础,后面会继续详细分析还有介绍基于UDP网络编程。

源码下载

1 0
原创粉丝点击