• Silverlight使用JavaSocket连接jabber服务器


    Silverlight使用JavaSocket连接jabber服务器

    一、开发环境

    Vs2010Sl4jdk6MyEclipse8.5

     

    二、Silverlight socket 使用 注意事项

    1、Silverlight Socket 数据交换端口必须在4502-4534范围 

    2、必须创建一个Socket监听943端口(该端口是固定的,客户端策略请求固定发送到该端口) 

     

    三、Silverlight Socket 访问介绍流程图

     

    四、服务器java端介绍以及代码

     

    1、去官网下载 smack jar包  http://www.igniterealtime.org/downloads/source.jsp

    2、引入jar包,如下:

    3、编写socket 的服务器端

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.PrintWriter;

    import java.net.ServerSocket;

    import java.net.Socket;

    import java.util.ArrayList;

    import java.util.List;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    import org.jivesoftware.smack.ConnectionConfiguration;

    import org.jivesoftware.smack.XMPPConnection;

     

    /**

     * @author geolo

     * 

     * @使用须知

     *    1. 每一个Socket客服端连接成功后会驻留在后台,因此在Jabber退出时一定要关闭自己的Socket,为保持客户端正常连接,所以不能采用垃圾收集器 <br />

     *    2. 连接Jabber的格式是 "userName,password".比如-->geolo,364200<-- 注意用“逗号”做分隔符 <br />

     *    3. 关闭Socket的格式是"Socket_Exit," 比如-->Socket_Exit,<--注意用“逗号”做尾符 <br />

     *    4. 如果Jabber登录成功会收到“LOGIN_TURE”提示 <br />

     *    5. 如果Jabber登录失败会收到“LOGIN_FALSE”提示   <br />

     *    6. 服务器Socket只有在重启的时候才会被关闭,否则一直保持等待客服端Socket登录状态。  <br />

     *    7. 服务器的IP视本机地址而定。端口号位4502.  <br />

     *    8. 感谢使用.

     */

    public class Server{

    //服务器端口

    private static final int SERVERPORT = 4502; 

    //客户端连接

    private static List<Socket> mClientList = new ArrayList<Socket>(); 

    //线程池

    private ExecutorService mExecutorService;  

    //ServerSocket对象

    private ServerSocket mServerSocket;  

    //Jabber连接对象

    XMPPConnection xmppConnection;

     

    //开启服务器

    public static void main(String[] args){

    new Server();

    }

     

    public Server(){

    try{

    //设置服务器端口

    mServerSocket = new ServerSocket(SERVERPORT);

    //创建一个线程池

    mExecutorService = Executors.newCachedThreadPool();

    System.out.println("start...");

    try {

     

    //用来临时保存客户端连接的Socket对象

    Socket client = null;

    while (true){

    //接收客户连接并添加到list

    client = mServerSocket.accept(); 

    mClientList.add(client);

     

    //设置Jabber端口  

    xmppConnection = new XMPPConnection(new ConnectionConfiguration("wyu.0101.com.cn", 5222));

    xmppConnection.connect();//连接Jabber

    System.out.println("连接成功");

     

    //开启一个客户端线程

    mExecutorService.execute(new ThreadServer(xmppConnection,client));

    }

    } catch (Exception e) {

    System.out.println("连接失败");   e.printStackTrace();

    }

    }

    catch (IOException e){

    System.out.println("登录失败3");

    e.printStackTrace();

    }

    }   

     

    //每个客户端单独开启一个线程

    static class ThreadServer implements Runnable{

    private SocketmSocket;

    private BufferedReadermBufferedReader;

    private PrintWritermPrintWriter;

    private StringmStrMSG;

    XMPPConnection connection;

    String isLogined;//登录是否成功

     

    public ThreadServer(XMPPConnection xmppConnection,Socket socket) throws IOException{

    if(this.mSocket != socket && this.connection != xmppConnection){

    this.mSocket = socket;

    this.connection = xmppConnection;

    }

     

    mBufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    sendMessage(mSocket,"Socket: "+this.mSocket.getInetAddress());

    }

     

    public void run(){

    try{

    while ((mStrMSG = mBufferedReader.readLine()) != null){

    isLogined = "LOGIN_FALSE";

    if(mStrMSG.indexOf(",") < 0){

    sendMessage(mSocket,isLogined);

    }else{

    String strArray[] = mStrMSG.split(",");

    if (strArray[0].trim().equalsIgnoreCase("Socket_Exit")){

    sendMessage(mSocket,"Socket closed");

    //当一个客户端退出时

    mClientList.remove(mSocket);

    mBufferedReader.close();

    mPrintWriter.close();

    mSocket.close();

    connection.disconnect();

    break;

    }else{

    try {

    System.out.println("name: "+strArray[0]+" password: "+strArray[1]);

    connection.login(strArray[0], strArray[1]);

    isLogined = "LOGIN_TURE";

    } catch (Exception e) {

    isLogined = "LOGIN_FALSE";

    System.out.println("错误2");

    }

    }

    }

    sendMessage(mSocket,isLogined);

    }

    }catch (Exception e){

    System.out.println("错误3");

    }

    }

     

    //发送消息给所对应的客户端

    private void sendMessage(Socket client,String message) throws IOException{

    mPrintWriter = new PrintWriter(client.getOutputStream(), true);

    mPrintWriter.println(message);

    }

    }

    }

     

    4、运行 java Appcation

    五、客服端 silverlight socket 介绍以及源码

    1、界面设计如下:

    2、界面代码

    <UserControl x:Class="SlToJavaSocket.MainPage"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        mc:Ignorable="d"

        d:DesignHeight="300" d:DesignWidth="400">

        <Grid  Name ="LayoutRoot"  Background ="White"  ShowGridLines ="True">

            <Grid.RowDefinitions >

                <RowDefinition />

                <RowDefinition />

            </Grid.RowDefinitions >

            <TextBox x:Name="txtToSend" Grid.Row ="0"/>

            <Button Grid.Row ="1" Click ="OnSend" Content ="Send" Margin ="20" />

        </Grid >

    </UserControl>

     

    3、后台代码

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Net;

    using System.Windows;

    using System.Windows.Controls;

    using System.Windows.Documents;

    using System.Windows.Input;

    using System.Windows.Media;

    using System.Windows.Media.Animation;

    using System.Windows.Shapes;

    using System.Net.Sockets;

    using System.Threading;

    using System.Text;

     

    namespace SlToJavaSocket

    {

        public partial class MainPage : UserControl

        {

            public MainPage()

            {

                InitializeComponent();

            }

     

            // 定义一个可在全局使用的Socket

     

            System.Net.Sockets.Socket socket;

     

     

     

            // 定义一个同步上下文类,用来将子线程的操作调度到主线程上以可控制UI 属性。

     

            SynchronizationContext syn;

     

     

     

            // 发送信息按钮的单击事件

     

            void OnSend(object sender, RoutedEventArgs args)

            {

     

     

                // 定义一个字节数组,并将文本框的的类容转换为字节数组后存入

     

                byte[] bytes = Encoding.UTF8.GetBytes(txtToSend.Text);

     

     

     

                // 显示信息,可不要。

     

                txtToSend.Text += "\r\nDnsSafeHost:" + Application.Current.Host.Source.DnsSafeHost;

     

     

     

                // 将同步上下文设置在当前上下文(线程,主线程,可控制UI 的)

     

                syn = SynchronizationContext.Current;

     

     

     

                // 为socket 创建示例,并设置相关属性。

     

                socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

     

     

     

                // 定义并实例一个Socket 参数

     

                SocketAsyncEventArgs socketArgs = new SocketAsyncEventArgs();

     

     

                socketArgs.SocketClientAccessPolicyProtocol = SocketClientAccessPolicyProtocol.Tcp;

                // 设置到远程终节点属性(4502 端口,为什么是4502 ,MS 的SL 通信安全上有)

     

                //socketArgs.RemoteEndPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, 4510);

                socketArgs.RemoteEndPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, 4502);

     

     

                // 设置好当Socket 任何一个动作完成时的回调函数。

     

                socketArgs.Completed += new EventHandler<SocketAsyncEventArgs>(socketArgs_Completed);

     

                //Socket 参数的用户标识,实际上就是一个可以传递的OBJECT 参数。

     

                socketArgs.UserToken = bytes;

     

                // 执行连接。

     

               MessageBox.Show( (socket.ConnectAsync(socketArgs)).ToString());

     

     

            }

     

     

     

            void socketArgs_Completed(object sender, SocketAsyncEventArgs e)

            {

     

                // 当任何一个Socket 动作完成,都回调该函数,然后对LastOperation 进行判断后继续执行相应的部分

     

                switch (e.LastOperation)

                {

     

                    case SocketAsyncOperation.Connect:

     

                        ProcessConnect(e);

     

                        break;

     

                    case SocketAsyncOperation.Receive:

     

                        ProcessReceive(e);

     

                        break;

     

                    case SocketAsyncOperation.Send:

     

                        ProcessSend(e);

     

                        break;

     

                }

     

            }

     

     

     

            // 将数据放入buffer 并进行异步发送

     

            void ProcessConnect(SocketAsyncEventArgs e)

            {

     

     

     

                // 当连接成功后,获取Socket 参数 e 传递过来的用户标识(也就是本示例中用户输入的字符串转换的Byte 字节数组)

     

                byte[] bytes = (byte[])e.UserToken;

     

     

     

                // 设置Socket 参数的缓冲区参数,将我们的字节数组设置为Socket 的缓冲区。

     

                e.SetBuffer(bytes, 0, bytes.Length);

     

     

     

                // 同步一下上下文,显示一下当前的状态信息。

     

                syn.Post(GetText, "States:" + e.SocketError.ToString() + "," + e.LastOperation.ToString());

     

     

     

                // 发送数据

     

                socket.SendAsync(e);

     

     

     

            }

     

     

     

            // 发送完成后,执行等待接收服务器发回的数据

     

            void ProcessSend(SocketAsyncEventArgs e)

            {

     

                // 定义个空的字节数组,设置好其大小

     

                byte[] bytes = new byte[1024];

     

                // 将前面定义字节数组设置成缓冲区

     

                e.SetBuffer(bytes, 0, bytes.Length);

     

                // 执行异步接收

     

                socket.ReceiveAsync(e);

     

            }

     

     

     

            // 当接收完成后

     

            void ProcessReceive(SocketAsyncEventArgs e)

            {

     

                // 在执行好接收后,本地SOCKET 的缓冲区就会被服务器发送的数据填充。

     

                // 显示下信息,当然也是用同步上下文的方式,在显示信息的时候,就直接将缓冲区的字节数组转换成字符串。

     

                syn.Post(GetText, Encoding.UTF8.GetString(e.Buffer, 0, e.Buffer.Length) + " and Received");

     

                // 关闭Socket 连接

     

                socket.Close();

     

                // 最后显示下,Socket 关闭。

     

                syn.Post(GetText, "Socket Closed");

     

            }

     

     

     

            // 同步上下文调用的方法。

     

            void GetText(object str)

            {

     

                txtToSend.Text += "\r\n" + str.ToString();

     

            }

     

     

        }

    }

     

    六、运行效果

     

    1Silverlight端运行效果:

    2、java端运行效果

    3、恭喜,连上 服务器(lxflxf 是指我在服务器上注册的用户名和密码)

     

    七、注意事项

     

    1、把 策略文件放到  服务器 943 端口 (类似于开个socket , 发送 策略文件)

    2、Silverlight 对外端口 4502-4534 (设置超过或小于后果自负)

    3、如果是win7 系统的一定要注意 IIS中 用户的权限(我就在这悲剧了半天~

     

     

  • 相关阅读:
    poj3673
    poj3438
    poj3461
    poj3518
    poj3672
    变秃了,也变强了!爆肝吐血整理出的超硬核JVM笔记分享!
    左手字节,右手阿里,我是如何通阿里架构师的java面试文档,拿到多家大厂offer的
    Java异常处理与常用类
    copy_{to, from}_user()的思考
    vi文本编辑器常用指令功能
  • 原文地址:https://www.cnblogs.com/luxiaofeng54/p/1891408.html
Copyright © 2020-2023  润新知