这是一种见得模拟qq的即时传讯程序。
一、建立服务端
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 建立服务端
* @author
*
*/
public class TestServerSocket {
public static void main(String[] args) {
//设置为null是因为用完要在finally里面close();
ServerSocket ss =null;
Socket s1= null;
DataOutputStream dos =null;
try {
//设置服务的端口名为9999,一般设置四位数,1024以下的基本上被电脑所占用所以最好写大一点
ss =new ServerSocket(9999);
System.out.println("服务端开始运行了");
s1 = ss.accept();//侦听开始,返回的是Socket类型
//DateOutputStream里的参数是OutputStream,我们通过Socket里的getOutputStream获得
dos = new DataOutputStream(s1.getOutputStream());
//调用write方法写东西传过去。
dos.writeUTF("aa");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//释放资源
try {
if(ss!=null)
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(s1!=null)
s1.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(dos!=null)
dos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
建立客户端
package com.lqx.testsocket;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端
* @author
*
*/
public class TestCoilen {
public static void main(String[] args) {
Socket cs =null;
DataInputStream dis = null;
try {
//Socket的构造方法里一个参数是地址,一个是端口。这里的127.0.0.1是本地的意思。如果要连接其他的服务端需要输入对应的IP地址和端口号
cs =new Socket("127.0.0.1", 9999);
dis = new DataInputStream(cs.getInputStream());
//使用read方法可以读出来。
System.out.println(dis.readUTF());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(cs!=null)
cs.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(dis!=null)
dis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
输出
服务端要先运行
然后在运行客户端
– 可以看出在客服端接收并输出了aa。
改进
这里只进行了一次的传输,如果想要多次传输,只需在read和write方法外加一个while方法即可
while(true) {
dos.writeUTF("aa");}
while(true) {
System.out.println(dis.readUTF());
}
虽然进行了多次的传输,但是我相信大家也发现了,他是单向的传输,如果想要双向,其实很简单,只需要在服务端和客户端各自加上想要的write和read方法即可,如下
DataOutputStream dos = new DataOutputStream(cs.getOutputStream());
while(true) {
System.out.println(dis.readUTF());
dos.writeUTF("bbb");
}
dos = new DataOutputStream(s1.getOutputStream());
//调用write方法写东西传过去。
while(true) {
dos.writeUTF("aa");
System.out.println(dis.readUTF());
}
我这样子两个控制台会分别收到aa和bbb。如果我把里面的字符串aa和bbb替换成Scanner的输入即可完成信息的传递,不过,这个方法是阻塞的所以只能一次一次的接收和发送。
上面的只能单对单的进行数据的传递,如果想要实现,对n的信息传递。类似于群聊。就需要使用到多线程。
也就是说在服务器里开启多个线程,当外部客户端需要访问时就创造一个线程对话,但是这方法也是阻塞的。也就是说一次只能传递一个消息
public static void main(String[] args) {
ServerSocket ss;
try {
ss = new ServerSocket(9999);
System.out.println("服务器开始运行");
while (true) {
Socket s = ss.accept();
//这是new出来的一个线程。里面是一个new runnable的方法内部类。
new Thread(new Runnable() {
DataInputStream dis = null;
DataOutputStream dos = null;
Scanner sc = new Scanner(System.in);
//重写里面的run方法。
@Override
public void run() {
try {
dos = new DataOutputStream(s.getOutputStream());
dis = new DataInputStream(s.getInputStream());
while (true) {
String msg = Thread.currentThread().getName()+dis.readUTF();
System.out.println(msg);
dos.writeUTF(sc.next());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if (dos != null)
try {
dos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
}
//这里省略了,直接就start了
}).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
主要是改一下服务器的代码就行了。跟上面的对比就多加了多线程。