java基础-socket

Socket的定义

 

网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。

Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,

一个Socket由一个IP地址和一个端口号唯一确定。

Socket通讯的过程

 

Server端Listen(监听)某个端口是否有连接请求,Client端向Server 端发出Connect(连接)请求,

Server端向Client端发回Accept(接受)消息。一个连接就建立起来了。

Server端和Client 端都可以通过Send,Write(socket.getOutputStream/socket.getInputStream)等方法与对方通信。

对于一个功能齐全的Socket,都要包含以下基本结构,其工作过程包含以下四个基本的步骤:

1. 创建Socket;

2. 打开连接到Socket的输入/出流;

3. 按照一定的协议对Socket进行读/写操作;

4.关闭Socket.(在实际应用中,并未使用到显示的close,虽然很多文章都推荐如此,不过在我的程序中,可能因为程序本身比较简单,要求不高,所以并未造成什么影响。)

 

 

创建Socket

创建Socket在java包java.net中提供了两个类Socket和ServerSocket,

分别用来表示双向连接的客户端和服务端。这是两个封装得非常好的类,使用很方便。其构造方法如下:

 

客户端类的构造器:

  Socket(InetAddress address, int port);

  Socket(InetAddress address, int port, boolean stream);

  Socket(String host, int prot); //主要使用

  Socket(String host, int prot, boolean stream);

  Socket(SocketImpl impl)

  Socket(String host, int port, InetAddress localAddr, int localPort)

  Socket(InetAddress address, int port, InetAddress localAddr, int localPort)

  

服务端类的构造器:

ServerSocket(int port);  //主要使用

  ServerSocket(int port, int backlog);

  ServerSocket(int port, int backlog, InetAddress bindAddr)

其中address、host和port分别是双向连接中另一方的IP地址、主机名和端 口号,stream指明socket是流socket还是数据报socket,localPort表示本地主机的端口号,localAddr和 bindAddr是本地机器的地址(ServerSocket的主机地址),impl是socket的父类,既可以用来创建serverSocket又可 以用来创建Socket。count则表示服务端所能支持的最大连接数。例如:

Socket client = new Socket("127.0.01", 5555);  //127.0.01任何时候都代表本机IP地址,5555是自定义的端口号

  ServerSocket server = new ServerSocket(5555);

  注意,在选择端口时,必须小心。每一个端口提供一种特定的服务,

只有给出正确的端口,才 能获得相应的服务。

0~1023的端口号为系统所保留,例如http服务的端口号为80,telnet服务的端口号为21,ftp服务的端口号为23, 

所以我们在选择端口号时,最好选择一个大于1023的数以防止发生冲突。

  在创建socket时如果发生错误,将产生IOException,在程序中必须对之作出处理。所以在创建Socket或ServerSocket是必须捕获或抛出例外。

 

 

 

 

 

 

 client.java

package client;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Client extends Thread {

    //定义一个Socket对象
    Socket socket = null;

    public Client(String host, int port) {
        try {
            //需要服务器的IP地址和端口号,才能获得正确的Socket对象
            socket = new Socket(host, port);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        //客户端一连接就可以写数据个服务器了
        new sendMessThread().start();
        super.run();
        try {
            // 读Sock里面的数据
            InputStream s = socket.getInputStream();
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = s.read(buf)) != -1) {
                System.out.println(new String(buf, 0, len));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //往Socket里面写数据,需要新开一个线程
    class sendMessThread extends Thread{
        @Override
        public void run() {
            super.run();
            //写操作
            Scanner scanner=null;
            OutputStream os= null;
            try {
                scanner=new Scanner(System.in);
                os= socket.getOutputStream();
                String in="";
                do {
                    in=scanner.next();
                    os.write(("客户端:"+in).getBytes());
                    os.flush();
                } while (!in.equals("bye"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            scanner.close();
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

clientTest.java

package client;

public class ClientTest {
    public static void main(String[] args) {
        //需要服务器的正确的IP地址和端口号
        Client client=new Client("192.168.1.7", 6768);
        client.start();
    }
}

service.java

package service;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
 服务器端继承Thread
 * 可以实现简单的交互
 * */
public class Server extends Thread {

    // 定义服务器接口ServerSocket
    ServerSocket server = null;

    // 定义一个服务器,定义端口
    public Server(int port) {
        try {
            server = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 发送消息的线程
    @Override
    public void run() {
        super.run();
        try {
            System.out.println("服务器在启动中...等待用户的连接");
            //一直接收用户的连接,连接之后发送一条短信给用户
            while(true){
                // 建立socket接口,accept方法是一个阻塞进程,等到有用户连接才往下走
                // 定义Socket类
                Socket  socket = server.accept();
                //通过socket对象可以获得输出流,用来写数据
                OutputStream os = socket.getOutputStream();
                // 向客户端发送消息
                os.write("服务器正在向你发送消息!".getBytes());
                //在服务器上显示连接的上的电脑、
                System.out.println(socket.getInetAddress().getHostAddress()+"连接上了!");
                //通过socket对象可以获得输入流,用来读取用户数据
                InputStream is=socket.getInputStream();
                //读取数据
                int len=0;
                byte[] buf=new byte[1024];
                while ((len=is.read(buf))!=-1) {
                    //直接把获得的数据打印出来
                    System.out.println("服务器接收到客户端的数据:"+new String(buf,0,len));
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

serviceTest.java

package service;


public class ServerTest {

    public static void main(String[] args) {

        //这里服务器只需要定义一个端口号就可以了,程序会自动获取IP地址
        //但是客户端需要连接这个服务器时,需要知道它的IP地址还有端口号
        //ip地址的查看方法:进入cmd窗口,输入ipconfig/all可以看到
        Server server=new Server(6768);
        server.start();
    }

}

 

posted @ 2020-05-30 14:08  To_Yang  阅读(257)  评论(0)    收藏  举报