先贴代码:客户端的代码
package connect;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;
public class ConnectTest extends Thread{
//
private String ip;//客户端需要连接的IP地址
//
private int port;
//客户端需要连接的端口号
//
private String cmd; //客户端想要发送的命令
//
//通过构造函数确定需要连接什么样的服务器和端口
//
public ConnectTest(String ip,int port) {
//
super();
//
this.ip = ip;
//
this.port = port;
//
}
//
//同上,初始化send的条件
//
public ConnectTest(String ip, int port, String cmd) {
//
super();
//
this.ip = ip;
//
this.port = port;
//
this.cmd = cmd;
//
}
//
//
//重写线程方法
//
public void run(){
//
A.sendMsg(ip, port,cmd);
//
}
/*
* 主函数开启多线程去发送信息
*/
//
try {
//
Thread.sleep(2000);
//
} catch (InterruptedException e) {
//
e.printStackTrace();
//
}
//
//
String ip = "127.0.0.1";
//
int port1 = 1234;
//
int port2 = 1235;
//
ConnectTest c = new ConnectTest(ip,port2,"123456");
//
for (int i = 0; i < 8; i++) {
//
ConnectTest test = new ConnectTest(ip, port1,i+"");
//
test.start();
//
}
//
try {
//
Thread.sleep(2000);
//
} catch (InterruptedException e) {
//
// TODO Auto-generated catch block
//
e.printStackTrace();
//
}
//
c.start();
public static void main(String[] args) {
A.sendMsg("127.0.0.1", 1234, "aaa");
A.sendMsg("127.0.0.1", 1234, "bbb");
A.sendMsg("127.0.0.1", 1234, "ccc");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
A.sendMsg("127.0.0.1", 1235, "ddd");
A.sendMsg("127.0.0.1", 1234, "eee");
}
}
//内部类确定对象唯一性,这样的话是同一类对象的线程会互斥,不是同一类对象的线程则是异步,用端口号来确定是否是同一对象。
class A{
private static HashMap
map = new HashMap();
private String ip;
private int port;
private A(String ip,int port) {
this.ip = ip;
this.port = port;
}
//为了创建单例对象
public synchronized static A getA(String ip,int port){
String key = getKey(ip, port);
if(map.containsKey(key)){
return map.get(key);
}else{
A a = new A(ip,port);
map.put(key, a);
return a;
}
}
private static String getKey(String ip,int port){
return ip+":"+port;
}
//锁同步方法可区别不同类去锁只有同一个类访问会锁上,不是同一个类不会锁
public synchronized void sendMsg(String msg){
DataOutputStream dos=null;
DataInputStream dis =null;
Socket s=null;
try {
//获取服务端的连接
s=new Socket(ip,port);
//获取socket对象的输出流
dos = new DataOutputStream(s.getOutputStream());
//获取socket对象的输入流,读取客户端的回复
dis=new DataInputStream(s.getInputStream());
//客户端进行写数据
dos.writeUTF(msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
dos.flush();
String msg_return = null;
if((msg_return = dis.readUTF())!=null){
System.out.println(getKey(ip, port)+"----"+"re:"+msg_return);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
dos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//封装发送命令的方法。
public static void sendMsg(String ip,int port,String cmd){
new Thread(new MyRunnable(ip, port, cmd)).start();
}
}
class MyRunnable implements Runnable{
private String ip;
private int port;
private String cmd;
public MyRunnable(String ip, int port, String cmd) {
super();
this.ip = ip;
this.port = port;
this.cmd = cmd;
}
@Override
public void run() {
// TODO Auto-generated method stub
A a = A.getA(ip,port);
a.sendMsg(cmd);
}
}
我这里开了两个端口去连接服务器。说一下要求,连接同一个端口时是互斥的也就是他们会阻塞,连接的如果是不同端口,那他们就各自执行各自的。互不影响。
然后是服务端,有人会问服务端怎么监听两个或者多个端口,下面的代码可以实现监听多个端口
服务端代码:
package connect;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务器
* @author Administrator
*
*/
public class Server extends Thread{
public int port;//公共相同的地址,只是根据端口不同,开启不同的线程
public Server(int port){
this.port=port;
}
//客户端根据不同的端口或者相同的端口进行写信息
@Override
public void run() {
try {
ServerSocket ss=new ServerSocket(port);//监听不同的端口
while(true){
Socket s=ss.accept();//获得与服务器对应的socket
//获得输入流进行读操作
DataInputStream dis=new DataInputStream(s.getInputStream());
DataOutputStream dos=new DataOutputStream(s.getOutputStream());
String content= dis.readUTF();
//回复客户端
dos.writeUTF(change(content));
if(content!=null){
System.out.println("来自客户端的输出:"+content);
}
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
Server s1=new Server(1234);
Server s2=new Server(1235);
s1.start();
s2.start();
}
/**
*
* @param b 任意字符串
* @return
* 通过该方法可以将小写字母转为大写字母,也可以将大写字母转换为小写字母
*/
public static String change(String b) {
char letters[] = new char[b.length()];
for(int i=0;i
char letter = b.charAt(i);
if(letter>='a' && letter<='z')
letter = (char) (letter-32);
else if(letter>='A' && letter<='Z')
letter = (char) (letter+32);
letters[i] = letter;
}
return new String(letters);
}
}
因为服务端要对客户端进行回复,所以我就找了个字母转换的方法。这样就可以实现效果。
然后是运行截图:
先启动服务端:
然后是客户端:

我们再看服务器端的输出:
这样就基本实现了所谓的socket的同步通信与异步通信了。上面用了客户端使用了HashMap有人知道是为什么吗?等回复。。。