java编程_socket_套接字_网络编程

============================================================ 

                                          1.实现server和client模型程序

============================================================ 

实现原理:

============================================================ 

服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,

在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),

等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。  

============================================================ 
客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,

关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

============================================================ 

服务器端代码:

package com.basic.socket.server;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * 服务器断的工作就是在指定的端口上监听
 * 1、建立连接
 * 2、打开输出流
 * 3、封装输出流
 * 4、向客户端发送数据
 * 5、关闭打开的输出流
 * 6、关闭打开的socket对象
 * 
 * @author HP
 * 
 * @time 2013-12-07
 * 
 * @version 1.0
 */
public class Chat_Server {
	public static void main(String[] args) {
		try {
			// 指定服务器端的端口号为8888
			ServerSocket s=new ServerSocket(8888);
			while(true){
				//建立连接
				Socket socket=s.accept();
				//打开输出流
				OutputStream os=socket.getOutputStream();
				//封装输出流
				DataOutputStream dos=new DataOutputStream(os);
				//s.getInetAddress()获取远程ip地址,s.getPort()远程客户端的断后好
				//向客户端发送数据
				dos.writeUTF("你好,客服端地址信息:"+socket.getInetAddress()+"\t客服端通讯端口号:"+socket.getPort());
				dos.writeUTF("i'm a server ,my name is Mercury!");
				//关闭打开的输出流
				dos.close();
				//关闭打开的socket对象
				socket.close();
			} //开始下一次循环
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
客户端代码:
package com.basic.socket.client;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
/**
 * 1、创建socket对象,指定服务器的ip地址,和服务器监听的端口号
 * 2、打开输入流
 * 3、封装输入流
 * 4、打印服务器端发送过来的信息
 * 5、关闭输入流
 * 6、关闭打开的socket对象
 * 
 * 客服端
 * 
 * @author HP
 *
 * @time 2013-12-07
 * 
 * @version 1.0
 */
public class Chat_Client {
	public static void main(String[] args) {
		try {
			// 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
			// 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
			// 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
			// refused: connect
			Socket socket=new Socket("127.0.0.1",8888);
			// 打开输入流
			InputStream is=socket.getInputStream();
			 // 封装输入流
			DataInputStream dis=new DataInputStream(is);
			// 打印服务器端发送过来的信息
			System.out.println(dis.readUTF());
			System.out.println(dis.readUTF());
			// 关闭输入流
			dis.close();
			// 关闭打开的socket对象
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

如果服务器端没有打开,这时候运行客户端,出现的结果:
java.net.ConnectException: Connection refused: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
    at java.net.Socket.connect(Socket.java:518)
    at java.net.Socket.connect(Socket.java:468)
    at java.net.Socket.<init>(Socket.java:365)
    at java.net.Socket.<init>(Socket.java:179)
    at com.b510.socket1703.TestClient.main(TestClient.java:19)
如果服务器端先打开服务,这时候客户端连接服务器端,出现的效果:
1 你好,客户端地址信息: /127.0.0.1    客户端通信端口号: 19712
2 i'm a server ,my name is Mercury!

============================================================ 

                                              2.实现单线程的聊天室

============================================================ 

服务器端代码:

package com.basic.socket.server;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
/**
 * 服务器断的工作就是在指定的端口上监听
 * 1、建立连接
 * 2、打开输出流
 * 3、封装输出流
 * 4、向客户端发送数据
 * 5、关闭打开的输出流
 * 6、关闭打开的socket对象
 * 
 * @author HP
 * 
 * @time 2013-12-07
 * 
 * @version 1.0
 */
public class Chat_Server_Simple {
	public static void main(String[] args) {
		try {
			// 指定服务器端的端口号为8888
			ServerSocket s=new ServerSocket(8888);
			//建立连接
			Socket socket=s.accept();
			//打开输出流
			OutputStream os=socket.getOutputStream();
			//封装输出流
			DataOutputStream dos=new DataOutputStream(os);
			//打开输入流
			InputStream is=socket.getInputStream();
			//封装输入流
			DataInputStream dis=new DataInputStream(is);
			//读取键盘输入流
			InputStreamReader isr=new InputStreamReader(System.in);
			//封装键盘输入流
			BufferedReader br=new BufferedReader(isr);
			
			String info;
			while(true){
				//接受客户端发送过来的信息
				info=dis.readUTF();
				//打印接受的信息
				System.out.println("对方说: " + info);
				//如果发现接受的信息为:bye,那么就结束对话
				if(info.equals("bye"))
					break;
					//读取键盘的输入流
					info=br.readLine();
					//写入到网络连接的另一边,即客户端
					dos.writeUTF(info);
					//如果服务器自己说:bye,也是结束对话
					if(info.equals("bye"))
						break;
			} //开始下一次循环
			
			//关闭打开的输入流
			dis.close();
			//关闭打开的输出流
			dos.close();
			//关闭打开的socket对象
			socket.close();
			s.close();
			
		} catch (SocketException e) {
			System.out.println("网络连接异常,程序退出!");
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
}

客户端代码:
package com.basic.socket.client;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
/**
 * 1、创建socket对象,指定服务器的ip地址,和服务器监听的端口号
 * 2、打开输入流
 * 3、封装输入流
 * 4、打印服务器端发送过来的信息
 * 5、关闭输入流
 * 6、关闭打开的socket对象
 * 
 * 客服端
 * 
 * @author HP
 *
 * @time 2013-12-07
 * 
 * @version 1.0
 */
public class Chat_Client_Simple {
	public static void main(String[] args) {
		try {
			// 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
			// 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
			// 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
			// refused: connect
			Socket socket=new Socket("localhost",8888);
			//打开输出流
			OutputStream os=socket.getOutputStream();
			//封装输出流
			DataOutputStream dos=new DataOutputStream(os);
			// 打开输入流
			InputStream is=socket.getInputStream();
			// 封装输入流
			DataInputStream dis=new DataInputStream(is);
			//读取键盘输入流
			InputStreamReader isr=new InputStreamReader(System.in);
			//封装键盘输入流
			BufferedReader br=new BufferedReader(isr);

			String info;
			while(true){
				//客户端先读取键盘输入信息
				info = br.readLine();
				//把他写入到服务器方
				dos.writeUTF(info);
				//如果客户端自己说:bye,即结束对话
				if(info.equals("bye"))
					break;
					//接受服务器端信息
					info = dis.readUTF();
					//打印
					System.out.println("对方说: " + info);
					//如果服务器自己说:bye,也是结束对话
					if(info.equals("bye"))
						break;
			}
			//关闭相应的输入流,输出流,socket对象
			dis.close();
			dos.close();
			// 关闭打开的socket对象
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

运行效果:

服务器端效果>>>

对方说: hell
你好
对方说: 嘿嘿
你今天
对方说: 13
代售点
客户端端效果>>>
hell
对方说: 你好
嘿嘿
对方说: 你今天?
13
对方说: 代售点?

当前的程序不管是服务器端,还是客户端,都是单线程的。如: 服务器端说:"你好"

1 //读取键盘的输入流
2 info = br.readLine();
3 //写入到网络连接的另一边,即客户端
4 dos.writeUTF(info);
5 //如果服务器自己说:bye,也是结束对话


通过上面的代码,把"你好"发送出去了,这时候,程序又开始循环,运行到:
1 //接受客户端发送过来的信息
2 info = dis.readUTF();

这段代码,其实在这里就阻塞在这里了。要等到客户端那边说了话,"嘿嘿",这时候这里的
阻塞才会变为非阻塞状态,然后又继续说,说完后又继续阻塞......

而对于客户端来说,其实是一样的道理,客户端说完"hello"后,进入:

1 //接受服务器端信息
2 info = dis.readUTF();

到收听服务器端的信息,在这里也产生了阻塞,只有服务器端说了"你好",这个阻塞才变为非阻塞
状态。然后又继续接下来的动作....

============================================================ 

                                              3.实现多线程的聊天室

============================================================ 

服务器端代码:

package com.basic.socket.server;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Test_Chat_Server {
	public static void main(String args[]) {
        try {
            // 创建一个socket对象
            ServerSocket s = new ServerSocket(8888);
            // socket对象调用accept方法,等待连接请求
            Socket s1 = s.accept();

            // =========服务器端,在这里应该先打开输出流,在打开输入流,
            // =========因为服务器端执行的操作是先听,再说,听,说,听,说.....

            // 打开输出流
            OutputStream os = s1.getOutputStream();
            // 封装输出流
            DataOutputStream dos = new DataOutputStream(os);
            // 打开输入流
            InputStream is = s1.getInputStream();
            // 封装输入流
            DataInputStream dis = new DataInputStream(is);
            // 创建并启用两个线程
            new MyServerReader(dis).start();
            new MyServerWriter(dos).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 接受并打印客户端传过来的信息
class MyServerReader extends Thread {
    private DataInputStream dis;

    public MyServerReader(DataInputStream dis) {
        this.dis = dis;
    }

    public void run() {
        String info;
        try {
            while (true) {
                // 如果对方,即客户端没有说话,那么就会阻塞到这里,
                // 这里的阻塞并不会影响到其他线程
                info = dis.readUTF();
                // 如果状态有阻塞变为非阻塞,那么就打印接受到的信息
                System.out.println("对方说: " + info);
                if (info.equals("bye")) {
                    System.out.println("对方下线,程序退出!");
                    System.exit(0);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 从键盘获得输入流并写入信息到客户端
class MyServerWriter extends Thread {
    private DataOutputStream dos;

    public MyServerWriter(DataOutputStream dos) {
        this.dos = dos;
    }

    public void run() {
        // 读取键盘输入流
        InputStreamReader isr = new InputStreamReader(System.in);
        // 封装键盘输入流
        BufferedReader br = new BufferedReader(isr);
        String info;
        try {
            while (true) {
                info = br.readLine();
                dos.writeUTF(info);
                if (info.equals("bye")) {
                    System.out.println("自己下线,程序退出!");
                    System.exit(0);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端代码:
package com.basic.socket.client;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class Test_Chat_Client {
	public static void main(String args[]) {
        try {
            // 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
            // 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
            // 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
            // refused: connect
            Socket s1 = new Socket("127.0.0.1", 8888);

            // =========客户端,在这里应该先打开输入流,在打开输出流,
            // =========因为客户端执行的操作是先说,再听,说,听,说,听.....

            // 打开输入流
            InputStream is = s1.getInputStream();
            // 封装输入流
            DataInputStream dis = new DataInputStream(is);
            // 打开输出流
            OutputStream os = s1.getOutputStream();
            // 封装输出流
            DataOutputStream dos = new DataOutputStream(os);

            // 创建并启用两个线程
            new MyClientReader(dis).start();
            new MyClientWriter(dos).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 接受并打印服务器端传过来的信息
class MyClientReader extends Thread {
    private DataInputStream dis;

    public MyClientReader(DataInputStream dis) {
        this.dis = dis;
    }

    public void run() {
        String info;
        try {
            while (true) {
                info = dis.readUTF();
                System.out.println("对方说: " + info);
                if (info.equals("bye")) {
                    System.out.println("对方下线,程序退出!");
                    System.exit(0);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 从键盘获得输入流并写入信息到服务器端
class MyClientWriter extends Thread {
    private DataOutputStream dos;

    public MyClientWriter(DataOutputStream dos) {
        this.dos = dos;
    }

    public void run() {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        String info;
        try {
            while (true) {
                info = br.readLine();
                dos.writeUTF(info);
                if (info.equals("bye")) {
                    System.out.println("自己下线,程序退出!");
                    System.exit(0);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端运行效果:
1 这是客户端
2 我是hongten
3 这是我说的第三句话,haha
4 对方说: 我是服务器端,这说我说的第一句话,hehe

服务器端运行效果:
1 对方说: 这是客户端?
2 对方说: 我是hongten
3 对方说: 这是我说的第三句话,haha
4 我是服务器端,这说我说的第一句话,hehe
程序中加入了多线程后,不管是服务器端,还是客户端,都可以连续的说话,另一边连续的听...
学习资料 http://www.cnblogs.com/hongten/archive/2012/04/29/java_socket.html

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值