JAVA网络编程(Socket)

       在Java中,基于TCP协议实现的网络通信类有两个:Socket类和ServerSocket类,客户端使用的是Socket类,服务器端使用的是ServerSocket类。使用它们可以方便的完成信息的交互,客户端与服务器端的连接,由服务器端向客户端提供服务。

       Socket类建立连接的过程是:首先在服务器端指定一个用来等待连接的端口创建一个ServerSocket实例,然后在客户端通过规定一个主机与端口号创建一个Socket实例,连接到服务器上。ServerSocket类的accept方法使服务器处于阻塞状态,等待用户请求。

       Scoket通信程序基本过程(4个步骤):

     (1).在客户端和服务器端创建Scoket/ServerSocket实例。

     (2).打开连接到Socket的输入/输出流。

     (3).利用输入/输出流和Socket。

     (4)关闭Socket(I/O流是基于Socket管道的,当Socket关闭时,I/O流也随之关闭)。

       Socket连接过程如下图所示:


1.建立Socke连接
主要实现代码:
服务端:
try{
     ServerSocket server  = new ServerSocket(9000);//服务器端建立套接字服务
}
catch(IOException e){
     //
}
Socket socket = null;
try{
     socket = server.accept();//监听客户端连接
}
catch(IOException e){
   //
}


客户端:
try{
    Socket client = new Socket(host,9000);//客户端创建套接字
}
catch(IOException e){
   //
}


2.在客户端和服务器端同时打开输入/输出流

       Socket 提供方法getinputStream()和getOutputStream()来得到对应的输入/输出流,进行数据的读写操作,方法分别返回InputStream对象和OutpputStream对象。可以把它们封装在缓冲流中以提高程序的性能,主要代码如下所示:
//输入流
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(isr);
//输出流
InputStreamWriter isw = new InputStreamWriter(socket.getOutputStream());
InputStreamReader isr = new InputStreamReader(isw);



3.关闭输入/输出流

       在客户端和服务器端关闭Socket.

范例演示:
       创建一个简单的聊天程序为例演示Socket编程,该程序分为客户端和服务器端。服务器端能够接收到多个连接,客户端可以连接服务器,发送信息给服务器端,服务器接受消息,转发给所有客户。
实现结果如下图所示:



实现代码:
服务器端代码:

server.java
package com.venus.myscoket.server;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Vector;

public class Server {
    
    public Server(int port) throws Exception {//构造函数,参数为端口号
        //创建ServerSocket
        ServerSocket server = new ServerSocket(port);
        //不断接受客户信息
        while(true){
            //监听客户端的连接
            Socket conn = server.accept();
            //将服务器端的输入流封装到DataInputStream类中,该类支持与机器无关的编码方式
            DataInputStream in = new DataInputStream(conn.getInputStream());
            //读取用户信息
            String who = in.readUTF();
            System.out.println("Client+(Ip:"+conn.getInetAddress()+")"+who+"enter!"+"\n");
            
            //每次监听就创建一个线程
            ServerHander cn = new ServerHander(who,conn);
            
            cn.start();
        }
    }
    public static void main(String args[]) throws Exception{
        new Server(9013);
    }

}
class ServerHander extends Thread{
    Socket socket = null;
    DataInputStream in = null;
    DataOutputStream out = null;
    String who = null;
    //保护所有的客户端对象
    protected static Vector<ServerHander>clientlist = new Vector<ServerHander>();
    public ServerHander(String name,Socket socket) throws IOException {
        this.who = name;
        this.socket = socket;
        
        in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
    }
    @Override
    public void run() {
        try {
        clientlist.addElement(this);
        sendallclient("weclome  "+who+"  entered");
        //无限循环
            while(true){
                String msg = in.readUTF();
                sendallclient(who+" : "+msg);
                }
                

            } catch (IOException e) {
                System.out.println("client exit or error.");
            }finally{
                clientlist.removeElement(this);
                sendallclient(who+"left !");
                try {
                    socket.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    System.out.println("Connection has been closed");
                }
            }
            
    }
/**
 * 给客户端传递信息的方法
 * @param msg
 */
protected static void sendallclient(String msg){
    synchronized (clientlist) {//对客户端的vector加锁
        Enumeration<ServerHander> allclients = clientlist.elements();
        //遍历访问每个客户端对象
        while(allclients.hasMoreElements()){
            
            ServerHander serh = (ServerHander)allclients.nextElement();
            try {
                serh.out.writeUTF(msg);//向客户端发送信息
                serh.out.flush();//刷新输出流,保证内容输出
            } catch (IOException e) {
                // TODO Auto-generated catch block
                serh.interrupt();//终端线程
            }
            }
        }
    }
}


客户端代码:
Client.java
package com.venus.myscoket.server;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;


public class Client {
	public ServiceFrame sf;//客户端窗体
	private Socket csocket;//Socket对象
	private DataInputStream in;//输入流
	private DataOutputStream out;//输出流
	public static void main(String[] args){
		String who="";
		//获得输出流
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		//输出提示信息
		System.out.print("please input your name,and then please Enter :");
		try {
			//读取登录名
			who =  in.readLine().trim();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//调用Client构造函数
		new Client(who,"172.20.83.37",9013);
	} 
	

public Client(String who,String server,int port){
		//创建客户端窗体
		sf = new ServiceFrame("简单聊天");
		//添加键盘监听事件
		sf.sendFD.addKeyListener(new ActListener(this, sf));
		sf.addWindowListener(new ExitListener(this));
		try {
				//创建Socket对象
				csocket = new Socket(server ,port);
				//输入流
				in = new DataInputStream(new BufferedInputStream(csocket.getInputStream()));
				//输出流
				out = new DataOutputStream(new BufferedOutputStream(csocket.getOutputStream()));
				//向输出流输出who信息
				out.writeUTF(who);
				//刷新输出流
				out.flush();
			
			while(true){
				sf.showTA.append("--"+in.readUTF()+"\n");//在窗体输出信息
			}
			} catch (Exception e) {
				System.out.println("Server error!");
				this.close();
				System.exit(0);
			} 		
}


protected void send(String msg){//输出信息
	try {
		out.writeUTF(msg);
		out.flush();
	} catch (IOException e) {}
	}
protected void close(){
	try {
		sf.dispose();
	
		out.close();
		in.close();
		csocket.close();
	} catch (IOException e) {}
}
}

class ServiceFrame extends Frame{
	protected TextArea showTA;
	protected TextField sendFD;
	public ServiceFrame(String winnm){
		super(winnm);
		setLayout(new BorderLayout());
		add("North",showTA = new TextArea());
		showTA.setEditable(false);
		add("South",sendFD = new TextField());
		pack();
		show();
		sendFD.requestFocus();
	}
}
class ActListener extends KeyAdapter{
	Client client;
	ServiceFrame sFrame;
	public ActListener(Client c,ServiceFrame sf) {
		client = c;
		sFrame = sf;
	}
	public void keyPressed(KeyEvent e){
		if(e.getKeyCode() == KeyEvent.VK_ENTER){
			client.send(sFrame.sendFD.getText());
			sFrame.sendFD.setText("");
		}
		
	}
}
class ExitListener extends WindowAdapter{
	Client client;
	public ExitListener(Client c){
		client = c;
	}
	public void windowClosing(WindowEvent e){
		client.close();
		System.exit(0);
	}
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值