Socket(JAVA)通信_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Socket(JAVA)通信

Socket(JAVA)通信

 2014/6/11 19:39:23  乐小易  程序员俱乐部  我要评论(0)
  • 摘要:最近学到了Socket通信,其实在学校的课程--计算机网络,这个东西是必学的。。。只是自己上课没听,只为应付考试,这个也没怎么碰触。接触到这个,现在就讲一下最简单的聊天通信C/S模式的代码的编写。这里只谈一下最简单的C/S模式的聊天程序。显然分为客户端和服务器端。流程也很简单。服务端首先需要监听摸一个端口号。(由于1024以内的端口计算机通常内部程序在使用,所以我们最好监听端口号较大的。以8888为例。)//监听端口号为8888端口ServerSocketss=newServerSocket
  • 标签:Java socket
  最近学到了Socket通信,其实在学校的课程--计算机网络,这个东西是必学的。。。只是自己上课没听,只为应付考试,这个也没怎么碰触。接触到这个,现在就讲一下最简单的聊天通信C/S模式的代码的编写。
  这里只谈一下最简单的C/S模式的聊天程序
  显然分为客户端和服务器端。
  流程也很简单。服务端首先需要监听摸一个端口号。(由于1024以内的端口计算机通常内部程序在使用,所以我们最好监听端口号较大的。以8888为例。)
  //监听端口号为8888端口
  ServerSocket ss = new ServerSocket(8888);
  //等待客户端的访问
  Socket socket = ss.accept();
 
  这个时候客户端访问该端口
  Socket socket = new Socket("localhost",8888);
  或者:
  Socket socket = new Socket("127.0.0.1",8888);
 
  这个时候两者的连接已经建立。
  怎么交换信息呢?在Socket中,无论是客户端还是服务器都是从socket.getInputStream()中获取到对方的信息,而将自己需要发送的信息写入到socket.getOutputStream()中。
  总结上面的也就是说,我们只需要建立连接,然后从socket.getInputStream()读取对方发送的信息,将自己需要发送的信息写入到socket.getOutputStream()中去快递给对方。

  再谈谈多线程
  当需要启动多个客户端时,客户端的编码部分是没有变化的。只需要改变服务器端。
  我们来观察整个通信过程,发现服务器端等待客户端接入时,执行ss.accept()来接受到客户端的Socket。但是当启动第二个时,就没有执行ss.accept()了。所以我们需要无限循环来一直接受客户端的接入(因为不知道有多少个客户端,所以就一直循环)。然后启动线程进行消息的接受与发送。(写一个线程类,重写run方法,将之前的接受与发送消息的代码直接复制就行了)
  具体代码如下:

  服务器:
  单线程:
class="java" name="code">package 群聊;

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

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Server {

	JTextArea jtx_output;
	JTextArea jtx_input;
	InputStream input;
	OutputStream output;
	/**
	 * 群聊服务器
	 * @param args
	 * @throws MalformedURLException
	 */
	public static void main(String[] args) throws MalformedURLException {
		// TODO 自动生成的方法存根
		new Server().showUI();
	}

	public void showUI() throws MalformedURLException {
		JFrame jf = new JFrame();
		jf.setTitle("群聊服务器");
		jf.setSize(new Dimension(420, 480));
		jf.setResizable(false);// 设置窗体大小不能改变
		jf.setLocationRelativeTo(null);
		jf.setDefaultCloseOperation(3);
		
		JPanel jpL = new JPanel();
		jpL.setPreferredSize(new Dimension(300, 400));

		JPanel jpR = new JPanel();
		jpR.setPreferredSize(new Dimension(100, 400));

		//设置带自动换行的只读文本区域
		jtx_output = new JTextArea();
		//不可编辑,只读文本
		jtx_output.setEditable(false);
		//jtx_input.setLineWrap(true);
		JScrollPane sp1 = new JScrollPane(jtx_output);
		sp1.setPreferredSize(new Dimension(300, 315));
		jpL.add(sp1);

		//设置头像显示按钮
		JButton jb = new JButton(new ImageIcon("images/头像1.jpg"));
		jpR.add(jb);

		//设置可输入自动换行的文本区域
		jtx_input = new JTextArea();
		// jtx_input.setLineWrap(true);
		JScrollPane sp2 = new JScrollPane(jtx_input);
		sp2.setPreferredSize(new Dimension(300, 100));
		jpL.add(sp2);

		//设置头像显示按钮
		JButton jb1 = new JButton(new ImageIcon("images/头像.JPEG"));
		jpR.add(jb1);

		JButton Jb = new JButton("发送");

		jf.add(jpL, BorderLayout.WEST);
		jf.add(jpR, BorderLayout.EAST);
		jf.add(Jb, BorderLayout.SOUTH);
		jf.setVisible(true);

		// 新建一个服务器套接字
		try {
			ServerSocket ss = new ServerSocket(8888);
			System.out.println("监听端口8888成功!");
			jtx_output.append("监听端口8888成功!");
			
			// 等待客户端的访问
			Socket socket = ss.accept();
		
			input = socket.getInputStream();
			output = socket.getOutputStream();
				
			//点击发送按钮,将服务器端的消息发送到客户端
			Jb.addActionListener(new ActionListener() {
				
				public void actionPerformed(ActionEvent e) {
				
					String out = jtx_input.getText()+"\n";
					jtx_output.append("服务器说    :"+out);
		           //将服务器段的消息发送给客户端
					try {
						byte[] bytes = out.getBytes("GBK");
						try {
							output.write(bytes);
							output.flush();
						} catch (IOException e1) {
						}
					} catch (UnsupportedEncodingException e1) {
					}
				}
			});

//			String msg = "Hello, 你好!聊天开始!";
//			jtx_output.append(msg);
//		    //写到客户端
//			byte[] bytes = msg.getBytes("GBK");
//			output.write(bytes);
            
			//接受客户端发来的消息
			while (true) {
				String line = readLine(input);
				jtx_output.append("客户端说    :"+line+"\n");
			}
		} catch (IOException e) {
		}
		
		
	}

	// 用来读取中文的方法
	public String readLine(InputStream input) throws IOException {
		// 字节输出流
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		while (true) {
			int n = input.read();
			// 以换行符为读取的间隔
			if (n == '\n')
				break;
			bos.write(n);
		}
		byte[] bytes = bos.toByteArray();
		return new String(bytes, "GBK");
	}


}
   多线程:
   (1)主类
    package 群聊;

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

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class ServerThread {

	JTextArea jtx_output;
	JTextArea jtx_input;
	

	/**
	 * 群聊服务器多线程
	 * @param args
	 * @throws MalformedURLException
	 */
	public static void main(String[] args) throws MalformedURLException {
		// TODO 自动生成的方法存根
		new ServerThread().showUI();
	}

	public void showUI() throws MalformedURLException {
		JFrame jf = new JFrame();
		jf.setTitle("群聊服务器");
		jf.setSize(new Dimension(420, 480));
		jf.setResizable(false);// 设置窗体大小不能改变
		jf.setLocationRelativeTo(null);
		jf.setDefaultCloseOperation(3);

		JPanel jpL = new JPanel();
		jpL.setPreferredSize(new Dimension(300, 400));

		JPanel jpR = new JPanel();
		jpR.setPreferredSize(new Dimension(100, 400));

		//设置带自动换行的只读文本区域
		jtx_output = new JTextArea();
		// 不可编辑,只读文本
		jtx_output.setEditable(false);
		// jtx_input.setLineWrap(true);
		JScrollPane sp1 = new JScrollPane(jtx_output);
		sp1.setPreferredSize(new Dimension(300, 315));
		jpL.add(sp1);

		// 设置头像显示按钮
		JButton jb = new JButton(new ImageIcon("images/头像1.jpg"));
		jpR.add(jb);

		// 设置可输入自动换行的文本区域
		jtx_input = new JTextArea();
		// jtx_input.setLineWrap(true);
		JScrollPane sp2 = new JScrollPane(jtx_input);
		sp2.setPreferredSize(new Dimension(300, 100));
		jpL.add(sp2);

		// 设置头像显示按钮
		JButton jb1 = new JButton(new ImageIcon("images/头像.JPEG"));
		jpR.add(jb1);

		JButton Jb = new JButton("发送");

		jf.add(jpL, BorderLayout.WEST);
		jf.add(jpR, BorderLayout.EAST);
		jf.add(Jb, BorderLayout.SOUTH);
		jf.setVisible(true);

		int i=0;
		
		// 新建一个服务器套接字
		try {
			ServerSocket ss = new ServerSocket(8888);
			jtx_output.append("监听端口8888成功!\n");

			// 循环多个客户端访问
			while (true) {
				i++;
				// 接受到客户端的访问
				Socket socket = ss.accept();
				// 启动线程来搭建和该客户端的连接
				SocketThread st = new SocketThread(socket,Jb,jtx_input,jtx_output,i);
				
				st.start();
			}
		} catch (IOException e) {
		}

	}


}
   (2)线程类
package 群聊;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JTextArea;

public class SocketThread extends Thread {
	public Socket socket;
	InputStream input;
	OutputStream output;
	int i;
	JButton Jb;
	JTextArea jtx_output;
	JTextArea jtx_input;

	// 构造方法传递客户端的socket
	public SocketThread(Socket scoket, JButton Jb, JTextArea jtx_input,
			JTextArea jtx_output, int i) {
		this.socket = scoket;
		this.Jb = Jb;
		this.jtx_input = jtx_input;
		this.jtx_output = jtx_output;
		this.i = i;
	}

	// 重写线程run方法
	public void run() {
		try {
			input = socket.getInputStream();
		} catch (IOException e2) {
		}

		try {
			output = socket.getOutputStream();
		} catch (IOException e2) {
		}
		
		
	    String outsay = "客户端" + i + "你好!"+"\n";
	    	byte[] bytess;
			try {
				bytess = outsay.getBytes("GBK");
				output.write(bytess);
			} catch (UnsupportedEncodingException e3) {
				// TODO 自动生成的 catch 块
				e3.printStackTrace();
			} catch (IOException e1) {
				// TODO 自动生成的 catch 块
				e1.printStackTrace();
			}
	    	
	    	
	    	
		// 点击发送按钮,将服务器端的消息发送到客户端
		Jb.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				String out = jtx_input.getText() + "\n";
			
				jtx_output.append("服务器说    :" + out+"\n");
				// 将服务器段的消息发送给客户端
				try {

					byte[] bytes = out.getBytes("GBK");
				
					try {
					
						output.write(bytes);
						output.flush();
					} catch (IOException e1) {
					}
				} catch (UnsupportedEncodingException e1) {
				} catch (IOException e2) {
					e2.printStackTrace();
				}
			}
		});

		// 接受客户端发来的消息
		while (true) {
			try {
				String line = readLine(input);
				jtx_output.append("客户端" + i + "说    :" + line + "\n");
			} catch (IOException e1) {
			}
		}
	}

	// 用来读取中文的方法
	public String readLine(InputStream input) throws IOException {
		// 字节输出流
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		while (true) {
			int n = input.read();
			// 以换行符为读取的间隔
			if (n == '\n')
				break;
			bos.write(n);
		}
		byte[] bytes = bos.toByteArray();
		return new String(bytes, "GBK");
	}
}

    客户端:
    package 群聊;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Client {

	
	JTextArea jtx_output;
	JTextArea jtx_input;
	InputStream input;
	OutputStream output;
	/**
	 * @param args
	 * @throws MalformedURLException 
	 */
	public static void main(String[] args) throws MalformedURLException {
		// TODO 自动生成的方法存根
       new Client().showUI();
	}
	
	public void showUI() throws MalformedURLException {
		JFrame jf = new JFrame();
		jf.setTitle("群聊客户器");
		jf.setSize(new Dimension(420, 480));
		jf.setResizable(false);// 设置窗体大小不能改变
		jf.setLocationRelativeTo(null);
		jf.setDefaultCloseOperation(3);

		JPanel jpL = new JPanel();
		jpL.setPreferredSize(new Dimension(300, 400));

		JPanel jpR = new JPanel();
		jpR.setPreferredSize(new Dimension(100, 400));

		// 设置带自动换行的只读文本区域
		jtx_output = new JTextArea();
		// 不可编辑,只读文本
		jtx_output.setEditable(false);
		// jtx_input.setLineWrap(true);
		JScrollPane sp1 = new JScrollPane(jtx_output);
		sp1.setPreferredSize(new Dimension(300, 315));
		jpL.add(sp1);

		// 设置头像显示按钮
		JButton jb = new JButton(new ImageIcon("管理员"));
		jpR.add(jb);

		// 设置可输入自动换行的文本区域
		jtx_input = new JTextArea();
		// jtx_input.setLineWrap(true);
		JScrollPane sp2 = new JScrollPane(jtx_input);
		sp2.setPreferredSize(new Dimension(300, 100));
		jpL.add(sp2);

		// 设置头像显示按钮
		JButton jb1 = new JButton(new ImageIcon("images/头像.JPEG"));
		jpR.add(jb1);

		JButton Jb = new JButton("发送");

		jf.add(jpL, BorderLayout.WEST);
		jf.add(jpR, BorderLayout.EAST);
		jf.add(Jb, BorderLayout.SOUTH);
		jf.setVisible(true);

		// 新建一个服务器套接字
		try {
			Socket ss = new Socket("127.0.0.1",8888);  
			input = ss.getInputStream();
		    output = ss.getOutputStream();
		    
		    Jb.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					String out = jtx_input.getText()+"\n";
					jtx_output.append("客户端说:"+out+"\n");
		           //将服务器段的消息发送给客户端
					try {
						byte[] bytes = out.getBytes("GBK");
						output.write(bytes);
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				}
			});

			//接受服务器端发来的消息
			while (true) {
				String line = readLine(input);
				jtx_output.append("服务器说    :"+line+"\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
	}

	// 用来读取中文的方法
	public String readLine(InputStream input) throws IOException {
		// 字节输出流
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		while (true) {
			int n = input.read();
			// 以换行符为读取的间隔
			if (n == '\n')
				break;
			bos.write(n);
		}
		byte[] bytes = bos.toByteArray();
		return new String(bytes, "GBK");
	}

}

 
 
  • 大小: 122.8 KB
  • 查看图片附件
发表评论
用户名: 匿名