============================================================
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