Socket学习

本文深入解析Java中的Socket和ServerSocket类,阐述了客户端与服务器如何通过Socket进行通信的基本原理及其实现过程,包括创建Socket实例、利用I/O流进行通信以及关闭Socket连接等关键步骤。

理论基础

  • Socket类
    Socket可以使一个应用从网络中读取和写入数据,不同计算机上的两个应用可以通过连接发送和接收字节流,当发送消息时,你需要知道对方的IP和端口,在Java中,Socket指的是Java.net.Socket类。
    以public Socket(String host, int port)为例,host为远程机器名称或ip地址,port为端口号。若连接本地的Server,其端口号为8080,可以写成如下格式
      new Socket(“localhost”, 8080);
    一旦成功创建一个Socket类的实例,可以用它来发送和接收字节流,发送时调用getOutputStream方法获取一个java.io.OutputStream对象,接收远程对象发送来的信息可以调用getInputStream方法来返回一个java.io.InputStream对象。

  • ServerSocket类
    Socket类代表一个客户端套接字,即任何时候连接到一个远程服务器应用时构建所需的socket。现在,要实现一个服务器应用,需要不同的做法。服务器需随时待命,因为不知道客户端什么时候会发来请求,此时,我们需要使用ServerSocket,对应的是java.net.ServerSocket类。
    ServerSocket与Socket不同,ServerSocket是等待客户端的请求,一旦获得一个连接请求,就创建一个Socket示例来与客户端进行通信。
    ServerSocket的构造函数也有多种重载形式:

  • 结论
    客户端:向服务器发送请求可分为以下步骤:
      1.创建一个Socket实例
       clientSocket = new Socket(“localhost”, 8080);
      2.利用I/O流与服务器进行通信
      InputStream is = clientSocket.getInputStream();
      OutputStream os = clientSocket.getOutputStream()
      3.关闭socket
    服务器:接收客户端请求步骤:
    1.创建一个ServerSocket实例,监听客户端发来的请求。
    server = new ServerSocket(8080);
    2.与客户端获取连接后,创建一个Socket实例,利用I/O流与客户端进行通信,完毕后关闭Socket。
    clientSocket = server.accept();
    InputStream is = clientSocket.getInputStream()
    OutputStream os = clientSocket.getOutputStream()

代码实现

服务器端

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class Myserver extends JFrame implements ActionListener, Runnable {
    JTextArea jTextReceive = new JTextArea();
    JTextField jTextSend = new JTextField();
    JButton jbs = new JButton("发送");
    ServerSocket server = null;
    JScrollPane jsp = new JScrollPane(jTextReceive);
    Socket clientSocket;     //负责当前线程中C/S通信中的Socket对象
    boolean flag = true;       //标记是否结束
    Thread connenThread;     //向客户端发送信息的线程
    BufferedReader sin;      //输入流对象
    DataInputStream sin1;
    DataOutputStream sout;   //输出流对象
    boolean flags = false;

    public static void main(String[] args) {
        Myserver MS = new Myserver();
        MS.serverStart();
    }
    public synchronized void changeFlag(boolean t){
       flags=t; 
    }
            

    public void serverStart() {
        try {
            server = new ServerSocket(8080);    //建立监听服务
            this.setTitle("服务器端,端口号:" + server.getLocalPort());
            this.setLayout(null);
            this.setBounds(20, 00, 300, 300);
            jsp.setBounds(20, 20, 220, 100);
            jTextSend.setBounds(20, 120, 220, 50);
            jbs.setBounds(20, 170, 220, 30);
            this.add(jsp);
            this.add(jTextSend);
            this.add(jbs);
            this.setVisible(true);
            jbs.addActionListener(this);
            while (flag) {
                clientSocket = server.accept();
                jTextReceive.setText("连接已经建立完毕!\n");
                try (InputStream is = clientSocket.getInputStream()) {
                    sin = new BufferedReader(new InputStreamReader(is));
                    try (OutputStream os = clientSocket.getOutputStream()) {
                        sin1 = new DataInputStream(clientSocket.getInputStream());
                        sout = new DataOutputStream(os);
                        connenThread = new Thread(this);
                        connenThread.start();     //启动线程,向客户端发送信息
                        String aLine;
                        while(true){
                            aLine=sin1.readUTF();
                            jTextReceive.append("客户端发来信息:" +aLine+"\n");
                            if (aLine.equals("bye")) {
                                flag = false;
                                connenThread.interrupt();
                                break;
                            }
                        }
                        sout.close();
                    }
                    sin.close();
                }
                clientSocket.close();     //关闭Socket连接
                System.exit(0);          //程序运行结束 
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException ex) {
                Logger.getLogger(Myserver.class.getName()).log(Level.SEVERE, null, ex);
            }
            try {
                    if (flags == true) {
                    changeFlag(false);
                    String str = jTextSend.getText().trim();
                   if(str==null||str.length()<=0){}
                    else{
                    sout.writeUTF(str);
                    sout.flush();
                    jTextReceive.append("服务器发送消息:"+str+"\n");   }            
                    jTextSend.setText("");
                    }

            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }

    @Override
    public void finalize() //析构方法
    {
        try {
            server.close();
        } //停止ServerSocket服务
        catch (IOException e) {
            System.out.println(e);
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JButton jbt = (JButton) e.getSource();
        if (jbt == jbs) //若单击确认对话框中的“发送”按钮
        {
            changeFlag(true);
        }
    }
}

  • 客户端
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

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


public class MyClient extends JFrame implements ActionListener, Runnable {

	     Socket clientSocket;
	    JTextArea jTextReceive = new JTextArea();
	    JTextField jTextSend = new JTextField();
	    JButton jbc = new JButton("发送");
	    JScrollPane jsp = new JScrollPane(jTextReceive);
	    boolean flag = true;                   //标记是否结束
	    Thread connenThread;                 //用于向服务器端发送信息
	    DataInputStream cin1;
	    DataOutputStream cout;
	    static boolean flagclient = false;
	    
	    
	    public synchronized void changeFlag(boolean t) {
	        flagclient = t;
	    }
	    
	    
	    public void clientStart() {
	        try {                              //连接服务器端,这里使用本机
	            this.setTitle("客户端,端口号:8080");
	            this.setLayout(null);
	            this.setBounds(20, 00, 300, 300);
	            jsp.setBounds(20, 20, 220, 100);
	            jTextSend.setBounds(20, 120, 220, 50);
	            jbc.setBounds(20, 170, 220, 30);
	            this.add(jsp);
	            this.add(jTextSend);
	            this.add(jbc);
	            this.setVisible(true);
	            jbc.addActionListener(this);
	            clientSocket = new Socket("localhost", 8080);
	            jTextReceive.setText("连接已经建立完毕!\n");
	            while (flag) {
	                try (InputStream is = clientSocket.getInputStream()) {
	                    cin1 = new DataInputStream(clientSocket.getInputStream());
	                    try (OutputStream os = clientSocket.getOutputStream()) {
	                        cout = new DataOutputStream(os);
	                        connenThread = new Thread(this);
	                        connenThread.start();     //启动线程,向服务器端发送信息
	                        String aLine;
	                        while (true) {
	                            aLine = cin1.readUTF();
	                            jTextReceive.append("服务器发来信息:" + aLine + "\n");
	                            if (aLine.equals("bye")) {
	                                flag = false;
	                                connenThread.interrupt();
	                                break;
	                            }
	                        }
	                        cout.close();
	                    }
	                    cin1.close();
	                }
	                clientSocket.close();    //关闭Socket连接
	                System.exit(0);
	            }
	        } catch (Exception e) {
	            System.out.println(e);
	        }
	    }
	    
	    
	    
	    public static void main(String[] args) {
	        new MyClient().clientStart();
	    }
	@Override
	public void run() {
		 while (true) {
	            try {
	                Thread.sleep(10);
	            } catch (InterruptedException ex) {
	                Logger.getLogger(MyClient.class.getName()).log(Level.SEVERE, null, ex);
	            }
	            try {
	                if (flagclient == true) {

	                    String str = jTextSend.getText().trim();
	                    if(str==null||str.length()<=0){}
	                    else{
	                    jTextReceive.append("发送消息:" + str + "\n");
	                    cout.writeUTF(str);
	                    cout.flush();}
	                    jTextSend.setText(null);
	                    changeFlag(false);
	                }

	            } catch (Exception e) {
	                System.out.println(e);
	            }
	        }
		
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		  JButton jbt = (JButton) e.getSource();
	        if (jbt == jbc) //若单击确认对话框中的“发送”按钮
	        {
	            changeFlag(true);
	        }
		
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值