* 首先,在这个实验中,我想要用我自己的方法,来实现一对一通信。
*
* 我想采用: 在服务器端建立一个数组,用于存储Socket
* 这样服务器端每创建一个socket,就存储一个,同时,每个客户端都有一个编号,
* 那么,客户端的编号也就是服务器返回给他的那个套接字的存储位置。
*
*
*
* */
package com.Server;
import javax.swing.*;
import java.io.*;
import java.net.*;
public class Onetoone_Server
{
/**
*我需要在服务器中建立一个全局变量数组
*Socket []
*在这个数组中我是这样定义的:
*
*在Socket[1]中我存放的是一号客户端与服务器的套接字连接信息,不管什么时候连接,1号位置只能分配给1号客户端
*在Socket[2]中我存放的是2号客户端与服务器连接的套接字,不管什么时候,2号位置只能分配给2号客户端
*同样三号位置我一定用来存放3号客户端,一次类推。。。
*
*那么客户端的编号我如何得到呢??
*
*
*这样,我把客户端的编号存储在服务器端的数据库中。每一次登录的时候,都会取出一个客户端编号
*
*
*
*
*
*
*
*
*
*/
Socket [] s_array=new Socket[20];
int i;
public static void main(String[] args) {
new Onetoone_Server();
// TODO Auto-generated method stub
}
// 书写服务器端的套接字
public Onetoone_Server()
{
try {
// 建立一个服务器套接字
ServerSocket ss=new ServerSocket(11111);
// 下面要做的就是如实现:在服务器端有一个父进程监听,同时当有连接时,创建一个子进程处理
//子线程要想能处理,客户端通信,那么,他就必须有服务器端,为这个客户创建的套接字。
// 但是,问题来了,什么时候把生成的套接字存储起来呢???
// z这个工作在什么地方做呢?
for(i=5;;)
{
Socket s=ss.accept();
s_array[i]=s;
System.out.println("已有客户端连接"+"编号是:"+i);
System.out.println("输出套接字");
System.out.println("本次的套接字是: "+s_array[i]);
i++;
new ServerFORClientThread(s).start();
// 其实,我可以这样想,在为客户端创建线程的同时,我也把该套接字方法它应该在的位置
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 我想在这里建立一个ServerFORClientThread
* 当我们创建线程的时候,那么这个线程的生存期是多少呢??
*
*
* 我要这个线程中作哪些事呢??
* 该线程的功能:
* 1.能从客户端1,中读取数据,
* 2.能把从客户端读取的数据,发送给相应的套接字
*
*
*
* */
class ServerFORClientThread extends Thread
{
// 定义线程类的构造函数
// 定义一个用户的id
Socket s=null;
Socket otherClient=null;
ServerFORClientThread(Socket s)
{
this.s=s;
}
public void run()
{
// 首先当客户端1与服务器建立连接时,
// 要先从中读取客户端的编号也就是用户id号
// 先假设已经读取到了客户端5发来的编号是5
// 客户端5要和客户端6通信,则从客户端发送给服务器的信息中也可以读取,它要和谁进程通信,那么 编号6 就是通信目的地
// 我认为应该是这样的,只有在套接字数组中存储了,通信双方的套接字之后,才可以从中取出。即:在取之前必须保证里面已经有了。
// 所以顺序是:先存,后取。
// 看来这样做是允许的啊
// 当把它存入之后,要做的就是,从这个套接字中读取信息,然后把信息写入另一个套接字通道
try {
DataInputStream dis=new DataInputStream(this.s.getInputStream());
String Clientcontent=dis.readUTF();
// 把信息写入另一个套接字管道中
// 先获取另一端的套接字
if(i<6)
otherClient =s_array[i+1];
else
otherClient=s_array[5];
//建立输出流,通信的另一端
DataOutputStream dos=new DataOutputStream(otherClient.getOutputStream());
// 把从客户端5中读取的信息写入客户端6的套接字管道中
dos.writeUTF(Clientcontent);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*下面是控制台的输出结果:
* 显示如下:
*
* 已有客户端连接编号是:5
输出套接字
本次的套接字是: Socket[addr=/127.0.0.1,port=51635,localport=11111]
已有客户端连接编号是:6
输出套接字
本次的套接字是: Socket[addr=/127.0.0.1,port=51639,localport=11111]
*
*
* 由此可以看出:
* 1.
* 在服务器是可以存储与该服务器建立连接的套接字的。
* 但是,如何使用存储在数组中的套接字呢???
*
* 2.我们也看到了,Socket 的结构是:客户端的ip 地址和客户端的端口号,以及与之连接的服务器端的端口。
* 那么,他们分别是什么作用呢??
*
*
*
*
*
*
* */
客户端代码:
package com.Client;
import java.io.*;
import java.net.*;
public class Client {
Socket s=null;
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new Client();
}
public Client()
{
try {
Socket s=new Socket("127.0.0.1",11111);
System.out.println("套接字已建立");
// 定义输入流
DataInputStream dis=new DataInputStream(s.getInputStream());
DataOutputStream dos=new DataOutputStream(s.getOutputStream());
while(true)
{
// String duqu=dis.readUTF();
//System.out.println("读取到的信息是: "+duqu);
System.out.println("请输入要发送的信息");
String st="你好";
System.out.println("发送的信息是: "+st);
dos.writeUTF(st);
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*下面是控制台的输出结果:
* 显示如下:
*
* 已有客户端连接编号是:5
输出套接字
本次的套接字是: Socket[addr=/127.0.0.1,port=51635,localport=11111]
已有客户端连接编号是:6
输出套接字
本次的套接字是: Socket[addr=/127.0.0.1,port=51639,localport=11111]
*
*
* 由此可以看出:
* 1.
* 在服务器是可以存储与该服务器建立连接的套接字的。
* 但是,如何使用存储在数组中的套接字呢???
*
* 2.我们也看到了,Socket 的结构是:客户端的ip 地址和客户端的端口号,以及与之连接的服务器端的端口。
* 那么,他们分别是什么作用呢??
*
*
*
*
*
*
* */