通信基础

[size=medium] 1.A和B两个机器要通信时,是A,B对应的程序要连接通信,就要知道对方的地址,通常所说的IP地址,它是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,即我们可以通过ip地址来确定一台机器,但是仅仅确定机器还不够,还要知道它所对应开放的是那个端口号,以便我们和对应的程序连接。[/size]
//建立绑定在指定端口上的服务器对象
ServerSocket server=new ServerSocket(port);
while(true){
//让服务器进入等待状态:阻塞状态
Socket client=server.accept();
//从连结对象上得到输入输出流对象
OutputStream out=client.getOutputStream();
InputStream ins=client.getInputStream();

[size=medium]此处循环的意义在于让服务器保持随时等待客户机来接的状态
(ps:客户机与服务器:在第一次连接中,主动请求的是客户机;等待连接的是服务器)
(ps:端口号0--65535,其中0--1024应避免使用,它们为知名端口)
创建好了服务器,就要传送数据,输入流读取,输出流发送,传送的都是字节,所以在传送时要做字节和字符串的转换。
字符串转为字节[/size]
String s="你好,欢迎来javaKe.com\r\n";
//取得组成这个字符串的字节
byte[] data=s.getBytes();
//用输出对象发送!
out.write(data);
out.flush();//强制输出
//最后关闭与客户机的连结
client.close();

[size=medium]字节转为字符串[/size]
        /**
* 从输入流中读取字节并拼成字符串 13为间断标识
* @param ins 输入流
* @return 读到的字符串
*/
private String readString(InputStream ins) throws Exception{
//创建一个字符串缓冲区
StringBuffer stb=new StringBuffer();
char c=0;
while(c!=13){
int i=ins.read();//读取客户机来的一个字节
c=(char)i;
stb.append(c);
}
String inputs=stb.toString().trim();
return inputs;
}

[size=medium] 2.上边实现了一对一连接,当有两个或多个客户机想连接时,就要用到线程,将每一个连接对象Socket交给一个线程处理,就不必等待。即将连接方法写在线程中[/size]
public void run(){
//在线程run中调用处理连结的方法
processChat(this.client);
//处理方法执行完毕后,线程自己即退出...
}

[size=medium]在服务器中启动线程
3.现在多个客户机可以同时与服务器连接,但只能显示自己的消息,看不到其他客户机的消息,下一步实现登录和所有客户端的消息接收。先要有一个用户的bean,包含用户帐号,密码等
然后登录,要有帐号和密码,一般情况是存在数据库中,然后进行查找是否存在此用户,这里可以使用“静态块”(“静态块”装载时就执行,即在属性初始化之前执行)在Dao类中初始化成员[/size]
//内存用户信息
private static Map<String,UserInfo> userDB=new HashMap();
//静态块:模拟生成内存中的用户数据
//当程序启动时,这段代码会自动执行,向userDB中存放数据
static{
for(int i=0;i<10;i++){
UserInfo user=new UserInfo();
user.setName("user"+i);
user.setPw("pw"+i);
//将指定的值与此映射中的指定键关联
userDB.put(user.getName(), user);
}
}

[size=medium](ps:关于静态块 java中的自由块分为静态的和非静态的 静态的即static{} class文件加载时执行一次,一般用来初始化静态变量的值;非静态自由块可以执行多次,初始化即会执行)
登录成功之后发消息时消息要发送到每一个客户端,即每个线程都要显示消息,遍历线程,显示消息ChatTools类[/size]
	private static List<ServerThread> stList=new ArrayList();
/**
* 让所有用户看到消息
* @param sender 发送者用户对象
* @param msg 要发送的内容消息
*/
public static void castMsg(UserInfo sender,String msg){
msg=sender.getName()+"说"+msg;
//遍历线程队列
for(int i=0;i<stList.size();i++){
//得到每一个线程对象
ServerThread st=stList.get(i);
try {
//每个线程对象都会输出此信息
st.sendMsg2Me(msg);//发送消息给每一个客户机
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
登录和发消息完成之后,要写线程,线程中要执行的方法:验证用户,读消息
//处理客户机进入的连接对象
private void processChat(){
try {
out=client.getOutputStream();
InputStream ins=client.getInputStream();
//字节快速转为字符串
BufferedReader brd= new BufferedReader(new InputStreamReader(ins));
sendMsg2Me("欢迎你来聊天!,请输入你的用户名:");
//读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行
String userName=brd.readLine();
sendMsg2Me(userName+",请输入你的密码:");
String pwd=brd.readLine();
user=new UserInfo();
user.setName(userName);
user.setPw(pwd);
//调用数据库模块,验证用户是否存在
boolean loginState=DaoTools.checkLogin(user);
if(!loginState){//不存在这个用户账号则关闭
this.closeMe();
return ;
}
//认证成功:将这个对象加入服务器队列
ChatTools.addClient(this);
//一行一行的读取客户机发来的消息
String input= brd.readLine();
while(!"bye".equals(input)){//一直读取
System.out.println("服务器收到的是: "+input);
//读到一条消息后,就发送给其他的客户机去...
ChatTools.castMsg(this.user, input);
input= brd.readLine();//读取下一条
}
}catch(Exception ef){
ef.printStackTrace();
}
ChatTools.castMsg(this.user, "我下线了,再见!");
this.closeMe();//关闭服务器方法
}

[size=medium] 最后就是服务器连接[/size]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值