Socket编程学习

Socket的服务器端需要在某个端口上开启服务器类型的Socket,即java.net.ServerSocket,通过它的accpet方法等待并接收客户端的请求,返回的是一个java.net.Socket对象,如果一直没有客户端的请求,那么accept方法将会一直等待。

Socket客户端根据服务器的IP地址(域名)和端口号创建一个Socket对象,连接服务器。

服务器端和客户端都持有一个Socket对象,服务器端的Socket从服务器端指向客户端,而客户端的Socket从客户端指向服务器端,就像在服务器端和客户端建立了两条单向的管道。

通过Socket类提供的getOutputStream方法获得Socket的输出流,getInputStream方法获得Socket的输入流。

实例如下:

package book.net.simplesocket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 *一个简单的Socket服务器,能接收客户端的请求,并将请求返回给客户端
 */
public class SimpleServer {
    ServerSocket serverSkt = null;//服务器端侦听的Socket
    Socket clinetSkt = null;//客户端
    BufferedReader in = null;//客户端输入流
    PrintStream out = null;//客户端输出流
    //构造方法
    public SimpleServer(int port){
        System.out.println("服务器代理正在监听,端口:" + port);
        try {
            serverSkt = new ServerSocket(port);//创建坚挺Socket
        } catch (IOException e) {
            System.out.println("监听端口" + port + "失败");
        }
        try {
            clinetSkt = serverSkt.accept();//接收连接请求
        } catch (IOException e) {
            System.out.println("连接失败");
        }
        try {
            in = new BufferedReader(new InputStreamReader(clinetSkt.getInputStream()));
            out = new PrintStream(clinetSkt.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //收到客户端请求
    public String getRequest(){
        String frmClt = null;
        try {
            frmClt = in.readLine();//从客户端的输入流中读取一行数据
            System.out.println("Server收到请求:" + frmClt);
        } catch (IOException e) {
            System.out.println("无法读取端口。。。。");
            System.exit(0);
        }
        return frmClt;
    }
    //发送响应给客户端
    public void sendResponse(String response){
        out.println(response);//往客户端输出流中写数据
        System.out.println("Server响应请求:" + response);
    }
    public static void main(String[] args) {
        SimpleServer sa = new SimpleServer(8888);//启动服务器
        while(true){
            //读取客户端的输入并返回给客户端
            sa.sendResponse(sa.getRequest());
        }
    }
}

package book.net.simplesocket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class SimpleClient {
    //客户端输入/输出流
    PrintStream out;
    BufferedReader in;
    //构造方法
    public SimpleClient(String serverName,int port){
        //根据服务器名和端口号,连接服务器
        try {
            Socket clientSocket = new Socket(serverName,port);
            out = new PrintStream(clientSocket.getOutputStream());
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        } catch (Exception e) {
            System.out.println("无法连接服务器!");
        }
    }
    //发送请求
    public void sendRequest(String request){
        out.println(request);
        System.out.println("Client发送请求:" + request);
    }
    public String getResponse(){
        String str = new String();
        try {
            str = in.readLine();
            System.out.println("Client收到Server返回:" + str);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return str;
    }
}

package book.net.simplesocket;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class ClientFrame extends JFrame implements ActionListener{
    JButton sendButton;//“发送”按钮
    JTextField inputField;//发送内容的输入框
    JTextArea outputArea;//服务器返回内容的文本域
    SimpleClient client;//客户端Socket对象
    //在构造函数中完成图形界面的初始化
    public ClientFrame(){
        JLabel label1 = new JLabel("输入:");
        inputField = new JTextField(20);
        JPanel panel1 = new JPanel();
        panel1.add(label1);
        panel1.add(inputField);
       
        JLabel label2 = new JLabel("服务器返回:");
        outputArea = new JTextArea(6,20);
        JScrollPane crollPane = new JScrollPane(outputArea);
        JPanel panel2 = new JPanel();
        panel2.setLayout(new BorderLayout());
        panel2.add(label2,BorderLayout.NORTH);
        panel2.add(crollPane,BorderLayout.CENTER);
       
        sendButton = new JButton("发  送");
        sendButton.addActionListener(this);
       
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(panel1, BorderLayout.NORTH);
        panel.add(sendButton,BorderLayout.CENTER);
        panel.add(panel2, BorderLayout.PAGE_END);
       
        setTitle("Socket客户端");
        this.getContentPane().add(panel);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    @Override
    public void actionPerformed(ActionEvent ae) {
        //判断事件源控价是否是“发送”按钮
        if(ae.getSource() == sendButton){
            client.sendRequest(inputField.getText());//发送文本框中的文本
            //接收服务器端回应并写入文本域
            outputArea.append(client.getResponse() + "\n");
        }
    }
    public static void main(String[] args) {
        ClientFrame frame = new ClientFrame();
        frame.pack();
        //连接服务器端
        frame.client = new SimpleClient("127.0.0.1",8888);
        frame.setVisible(true);
    }

}

分析:

1.SimpleServer类

该类实现了Socket服务器端。

(1)在构造方法中创建一个ServerSocket对象,侦听指定的端口,然后调用accept方法等待并接收客户端的请求,收到连接请求后,获取Socket的输入/输出流的引用。

(2)getRequest方法从Socket的输入流中读取来自客户端的请求消息,sendResponse方法将响应消息发送到Socket的输出流,即客户端。

(3)在main方法中,新建一个SimpleServer对象,然后不断地接收客户端的请求,将收到的请求按照原样返回给客户端。

2.SimpleClient类

该类实现了Socket客户端。

(1)在构造方法中,根据服务器端的IP地址和端口号创建一个Socket对象,此时便连接到服务器端,获得Socket的输入/输出流的引用。

(2)sendRequest方法向Socket的输出流中发送请求,即向服务器端发送请求:getResponse方法从Socket的输入流中读取信息,即获取服务器端的响应消息。

3.ClientFrame类

该类实现了客户端的图形化。

在文本框中输入请求消息,单击“发送”按钮,调用SimpleClient的sendRequest方法,将文本框中的消息发送给服务器端,然后调用SimpleClient的getResponse方法获得服务器端的响应消息,并显示在文本域中。

相关推荐