May
08

Как программно установить GPRS-соединение в Windows Mobile

Для того чтобы установить соединение с Internet в Windows Mobile предусмотрен специальный программный интерфейс – Connection Manager API.
Пользоваться им довольно просто. И вот пример такого использования для C# и C++ приведен ниже:

C# + .NET Compact Framework

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;

namespace GPRSConnection
{
    public class GPRSConnection
    {
        const int S_OK = 0;
        const uint CONNMGR_PARAM_GUIDDESTNET = 0x1;
        const uint CONNMGR_FLAG_PROXY_HTTP = 0x1;
        const uint CONNMGR_PRIORITY_USERINTERACTIVE = 0x08000;
        const uint INFINITE = 0xffffffff;
        const uint CONNMGR_STATUS_CONNECTED = 0x10;
        static Hashtable ht = new Hashtable();

        static GPRSConnection()
        {
            ManualResetEvent mre = new ManualResetEvent(false);
            mre.Handle = ConnMgrApiReadyEvent();
            mre.WaitOne();
            CloseHandle(mre.Handle);
        }

        ~GPRSConnection()
        {
            ReleaseAll();
        }

        public static bool Setup(Uri url)
        {
            return Setup(url.ToString());
        }

        public static bool Setup(string urlStr)
        {
            ConnectionInfo ci = new ConnectionInfo();
            IntPtr phConnection = IntPtr.Zero;
            uint status = 0;

            if (ht[urlStr] != null)
                return true;

            if (ConnMgrMapURL(urlStr, ref ci.guidDestNet, IntPtr.Zero) != S_OK)
                return false;

            ci.cbSize = (uint)Marshal.SizeOf(ci);
            ci.dwParams = CONNMGR_PARAM_GUIDDESTNET;
            ci.dwFlags = CONNMGR_FLAG_PROXY_HTTP;
            ci.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;
            ci.bExclusive = 0;
            ci.bDisabled = 0;
            ci.hWnd = IntPtr.Zero;
            ci.uMsg = 0;
            ci.lParam = 0;

            if (ConnMgrEstablishConnectionSync(ref ci, ref phConnection, INFINITE, ref status) != S_OK &&
                status != CONNMGR_STATUS_CONNECTED)
                return false;

            ht[urlStr] = phConnection;
            return true;
        }

        public static bool Release(Uri url)
        {
            return Release(url.ToString());
        }

        public static bool Release(string urlStr)
        {
            return Release(urlStr, true);
        }

        private static bool Release(string urlStr, bool removeNode)
        {
            bool res = true;
            IntPtr ph = IntPtr.Zero;
            if (ht[urlStr] == null)
                return true;
            ph = (IntPtr)ht[urlStr];
            if (ConnMgrReleaseConnection(ph, 1) != S_OK)
                res = false;
            CloseHandle(ph);
            if (removeNode)
                ht.Remove(urlStr);
            return res;
        }

        public static void ReleaseAll()
        {
            foreach (DictionaryEntry de in ht)
            {
                Release((string)de.Key, false);
            }
            ht.Clear();
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ConnectionInfo
        {
            public uint cbSize;
            public uint dwParams;
            public uint dwFlags;
            public uint dwPriority;
            public int bExclusive;
            public int bDisabled;
            public Guid guidDestNet;
            public IntPtr hWnd;
            public uint uMsg;
            public uint lParam;
            public uint ulMaxCost;
            public uint ulMinRcvBw;
            public uint ulMaxConnLatency;
        }

        [DllImport("cellcore.dll")]
        private static extern int ConnMgrMapURL(string pwszURL, ref Guid pguid, IntPtr pdwIndex);

        [DllImport("cellcore.dll")]
        private static extern int ConnMgrEstablishConnectionSync(ref ConnectionInfo ci, ref IntPtr phConnection, uint dwTimeout, ref uint pdwStatus);

        [DllImport("cellcore.dll")]
        private static extern IntPtr ConnMgrApiReadyEvent();

        [DllImport("cellcore.dll")]
        private static extern int ConnMgrReleaseConnection(IntPtr hConnection, int bCache);

        [DllImport("coredll.dll")]
        private static extern int CloseHandle(IntPtr hObject);
    }
}

Пример использования

public void DoTcpConnection()
        {
            string t = System.IO.Path.AltDirectorySeparatorChar.ToString() + System.IO.Path.DirectorySeparatorChar.ToString();
            string url = "www.msn.com";
            bool res = GPRSConnection.Setup(Uri.UriSchemeHttp + 
                Uri.SchemeDelimiter + url + Path.AltDirectorySeparatorChar);
            if (res)
            {
                TcpClient tc = new TcpClient(url, 80);
                NetworkStream ns = tc.GetStream();
                byte[] buf = new byte[100];
                ns.Write(buf, 0, 100);
                tc.Client.Shutdown(SocketShutdown.Both);
                ns.Close();
                tc.Close();
                MessageBox.Show("Wrote 100 bytes");
            }
            else
            {
                MessageBox.Show("Connection establishment failed");
            }
        }

C++

Singleton.h
#ifndef _SINGLETON_H
#define _SINGLETON_H

template class Singleton
{
public:
        static T & Instance()
        {
                static T instance;
                return instance;
        }
};

#endif
GPRSConnection.h
#pragma once

#include 
#include 
#include 
#include "Singleton.h"

class GPRSConnection : public Singleton
{
        friend class Singleton;
#ifndef _UNICODE
        typedef std::string StringType;
#else
        typedef std::wstring StringType;
#endif
        bool apiReady;
        std::map Connections;
protected:
        GPRSConnection() : apiReady(false)
        {
                do
                {
                        HANDLE apiHandle = ConnMgrApiReadyEvent();
                        if(!apiHandle) break;
                        if(WaitForSingleObject(apiHandle, 10000) != WAIT_OBJECT_0) break;
                        CloseHandle(apiHandle);
                        apiReady = true;
                }
                while(false);
        }
public:
        ~GPRSConnection()
        {
                ReleaseAll();
        }

        bool Setup(LPCTSTR url)
        {
                StringType urlInternal = url;
                if(Connections[urlInternal] != NULL) return true;
                CONNMGR_CONNECTIONINFO ci;
                if(ConnMgrMapURL(url, &ci.guidDestNet, NULL) != S_OK) return false;
                ci.cbSize = sizeof(CONNMGR_CONNECTIONINFO);
                ci.dwParams = CONNMGR_PARAM_GUIDDESTNET;
                ci.dwFlags = CONNMGR_FLAG_PROXY_HTTP;
                ci.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;
                ci.bExclusive = 0;
                ci.bDisabled = 0;
                ci.hWnd = NULL;
                ci.uMsg = 0;

                DWORD status = CONNMGR_STATUS_UNKNOWN;
                HANDLE phConnection;
                if (ConnMgrEstablishConnectionSync(&ci, &phConnection, -1, &status) != S_OK &&
                        status != CONNMGR_STATUS_CONNECTED) return false;

                Connections[urlInternal] = phConnection;
                return true;
        }

        bool Release(LPCTSTR url, bool removeNode)
        {
                StringType urlInternal = url;
                bool res = true;
                if(Connections[urlInternal] == NULL) return true;
                if (ConnMgrReleaseConnection(Connections[urlInternal], 1) != S_OK) res = false;
                CloseHandle(Connections[urlInternal]);
                if(removeNode)
                {
                        Connections.erase(urlInternal);
                }
                else 
                {
                        Connections[urlInternal] = NULL;
                }
                return res;
        }

        void ReleaseAll()
        {
                for(std::map::iterator i = Connections.begin(); i != Connections.end(); ++i)
                {
                        Release(i->first.c_str(), false);
                }
                Connections.clear();
        }
};

Пример использования

void MainFrame::OnCONNECTClick( wxCommandEvent& event )
{
        TransferDataFromWindow();
        bool res = GPRSConnection::Instance().Setup(m_URL.GetData());
        if(res)
        {
                wxLogMessage(_("Connection established"));
                // Дальше здесь можно делать всякие штуки
        }
        else
        {
                wxLogMessage(_("Connection error"));
        }
}

Скачать исходный код к статье (C++/C#)

Еще интересные посты о программировании для мобильных устройств:

5 Comments

Make A Comment
  • темка Said:

    спасибо то что нужно давно искал)) блок в закладки… Может еще подскажете почему httpReqaest не дожидается завершения скачивания потока на винмобайле? а скачивает 2 байта и понеслось дальнейшее выполнение кода(( а мне нужно чтобы всю страницу качало

  • T-Rex Said:

    Может еще подскажете почему httpReqaest не дожидается завершения скачивания потока на винмобайле?

    .NET CF? А 2 байта валидные скачивает или мустор?

  • темка Said:

    такую проблему заметил только при работе с 2 сайтами один из которых билайн…
    Решил проблему написав скачивание страницы через сокеты…
    А по предыдущему вопросу проблема такая… он скачивает всю страницу до конца и причем оч даже хорошо… но при это он скачивает 2-4 байта от страницы там типо куксы и все такое… дальше по идее должен грузить код самой страницы он это делает но при этом уже начинает выполнять действия с текстом страницы которую еще не докачал и вылетает ошибка по этой причине…

  • T-Rex Said:

    мм.. значит что-то ты не так делаешь.. а как ты проверяешь что страница вся скачалась? Если через сокеты то там надо читать пока не будет считано 0 байт, а потом уже что-то делать. Если страница больше 64к то она в один буфер не попадет, надо читать кусками до конца потока.

  • темка Said:

    нет я через обычный HttpWebRequest делал… щас конечно через сокеты по тихоньку учусь реализовывать не подскажешь мануал как через сокеты пост запросы делать?

Comments RSS Feed   TrackBack URL

Leave a comment

Please leave these two fields as-is:
купить садовые качели ; регистрация в контакте ; А желающих получить красивые фотографии - профессиональная фотосессия в студии .

top