Java_套接字

套接字

①网络通信使用IP地址标识Internet上的计算机,使用端口号标识服务器上的进程(程序)

②服务器上的每个程序都占用一个端口号,用于找到程序与程序交互信息

③端口号被规定为一个16位的0~65535之间的整数,其中**,0-1023被预先定义的服务通信占用**(如telnet占用端口23,http占用端口80等),除非我们需要访问这些特定服务,否则,就应该使用1024–65535这些端口中的某一个进行通信,以免发生端口冲突。

④当两个程序需要通讯时,它们可以通过使用socket类建立套接字对象并连接在一起(端口号与IP地址的组合得出一个网络套接字)

客户端套接字

客户端的程序使用Socket类建立负责连接到服务器的套接字对象
②Socket的构造方法是Socket(String host,int port),参数host是服务器的IP地址,port是一个端口号。建立套接字对象可能会发生IOException异常:

try{
	Socket mysocket = new Socket("http://192.168.0.78",2010);
}catch(IOException e){
}

当套接字对象mysocket建立后,mysocket可以使用方法getInputStream()获得一个输入流,这个输入流的源和服务器端的一个输入流的目的地刚好相同,因此客户端用输入流可以读取服务器写入到输出流中的数据
mysocket使用方法getOutputStream()获得一个输出流,这个输出流的目的地和服务器端的一个输入流的源刚好相同,因此服务器用输入流可以读取客户写入到输出流中的数据

ServerSocket对象与服务器端套接字

①客户负责建立连接到服务器的套接字对象,即客户负责呼叫。为了能使客户成功地连接到服务器,服务器必须建立一个ServerSocket对象,该对象通过将客户端的套接字对象和服务器端的一个套接字对象连接起来,从而达到连接的目的
②ServerSocket的构造方法是ServerSocket(int port),port是一个端口号。port必须和客户呼叫的端口号相同。建立ServerSocket对象可能发生IOException异常:

try{
	ServerSocket serverForClient = new ServerSocket(2010);
}catch(IOException e){
}

例如:2010端口已被占用时,就会发生IOException异常。
③当服务器的ServerSocket对象serverForClient建立后,就可以使用方法**accept()**将客户的套接字和服务器端的套接字连接起来。

try{
	Socket sc = serverForClient.accept();
}catch(IOException e){
}

所谓"接收"客户的套接字连接是指服务器端的ServerSocket对象:serverForClient调用accept()方法会返回一个与客户端Socket对象相连接的Socket对象sc
⑤驻留在服务器端的这个Socket对象sc调用getOutputStream()获得的输出流,将指向客户端Socket对象mysocket调用getInputStream()获得的那个输入流,即服务器端的输出流的目的地和客户端输入流的源刚好相同 ;同样,服务器端的这个Socket对象sc调用getInputStream()获得的输入流,将指向客户端Socket对象mysocket调用getOutputStream()获得的那个输出流,即服务器端的输入流的源和客户端输出流的源刚好相同
在这里插入图片描述
accept()方法也会阻塞线程的继续执行,直到接收到客户的呼叫。也就是说,如果没有客户呼叫服务器,那么下述代码中的System.out.println(“hello”)不会被执行:

try{
	Socket sc = server_socket.accept();
	System.out.println("hello");
}catch(IOException e){
}

连接建立后,服务器端的套接字对象调用getInetAddress()方法可以获取一个InetAddress对象,该对象含有客户端的IP地址和域名,同样,客户端的套接字对象调用getInputStream()方法可以获取一个InetAddress对象,该对象含有服务器端的IP地址和域名。
双方通信完毕后,套接字应使用close()方法关闭套接字连接
ServerSocket对象可以调用setTimeout(int timeout)方法设置超时值(ms),timeout是一个正值,当ServerSocket对象调用accept方法堵塞的时间一旦超过timeout时,将触发SocketTimeoutException。
在这里插入图片描述
在这里插入图片描述
Client.java

package SocketClass;

import java.io.*;
import java.net.*;

public class Client {
    public static void main(String []args){
        String []mess = {"1+1在什么情况下不等于2","狗为什么不生跳蚤","什么东西能看、能吃、能坐"};
        Socket mysocket;
        DataInputStream in = null;
        DataOutputStream out = null;
        try{
            mysocket = new Socket("127.0.0.1",2010);
            in = new DataInputStream(mysocket.getInputStream());
            out = new DataOutputStream(mysocket.getOutputStream());
            for(int i = 0;i < mess.length;i++){
                out.writeUTF(mess[i]);
                String s = in.readUTF();//in读取信息,堵塞状态
                System.out.println("客户收到服务器的回答"+s);
                Thread.sleep(500);
            }
        }catch (Exception e){
            System.out.println("服务器已断开"+e);
        }
    }
}

Server.java

package SocketClass;

import java.io.*;
import java.net.*;
public class Server {
    public static void main(String args[]){
        String []answer = {"在算错的情况下","狗只能生狗","电视、面包、沙发"};
        ServerSocket serverForClient = null;
        Socket socketOnServer = null;
        DataOutputStream out = null;
        DataInputStream in = null;
        try{
            serverForClient = new ServerSocket(2010);
        }catch (Exception e){
            System.out.println(e);
        }

        try{
            System.out.println("等待客户呼叫");
            socketOnServer = serverForClient.accept();//堵塞状态,除非有客户呼叫
            out = new DataOutputStream(socketOnServer.getOutputStream());
            in = new DataInputStream(socketOnServer.getInputStream());
            for(int i = 0;i<answer.length;i++){
                String s = in.readUTF();//in读取信息,堵塞状态
                System.out.println("服务器收到客户的提问:"+s);
                out.writeUTF(answer[i]);
                Thread.sleep(500);
            }
        }catch (Exception e){
            System.out.println("客户已断开"+e);
        }
    }
}

使用多线程技术

①需要注意的是,从套接字连接中读取数据与从文件中读取数据有着很大的不同。尽管二者都是输入流,但从文件中读取数据时,所有的数据都已经在文件中了,而使用套接字连接时,可能在另一端数据发送出来之前,就已经开始试着读取了,这时就会堵塞本线程,直到该读取方法成功读取到信息,本线程才能继续执行后序的操作。因此,服务器端接收到一个客户的套接字后,就应该启动一个专门为该客户服务的线程。
在这里插入图片描述
可以使用Socket类的不带参数的构造方法Socket()创建一个套接字对象,该对象再调用

public void connect(SocketAddress endpoint) throws IOException

请求和参数SocketAddress指定地址的服务器端的套接字建立连接
为了使用connect()方法,可以使用SocketAddress的子类InetSocketAddress创建一个对象,InetSocketAddress的构造方法是:
public InetSocketAddress(InetAddress addr ,int port)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章