2013年4月29日 星期一

DIY - 智能小車:Microsoft Windows Socket API 介紹 (二十六)

DIY - 智能小車:Microsoft Windows Socket API 介紹 (二十六)

筆者的智能小車是由 Microchip PIC16F877A 處理板控制,而小車的控制會由無線路由器 TP-Link TL-WR703N 發,控制訊息是利用無線 WiFi IEEE802.11 標準來傳送,在 PC 電腦的網絡會經由網線 IEEE802.3)連接另外一個無線路由器 Router 將訊息收發,所有網絡的硬件都是用 IEEE802 標準的。

智能小車控制圖
而網路程式的核心是 SocketSocket 是一組應用程式介面 (APIApplication Programming Interface) 介於應用程式與作業系統∕硬體之間,並提供標準的函式以符合不同的網路硬體規格,筆者是使用 Microsoft Visual Studio 2010 C++ 作網路編程,早在 1989 Berkeley 大學為了支援 UNIX 作業系統而發展了一套具備 TCP/IP 網路功能的 Berkeley Socket APIBSD sockets),Microsoft Berkeley Socket API 為基礎也發展出一套相似的 Socket 函式庫,即 Microsoft Windows Socket API (簡稱WinSock API),WinSock API 是一套動態連結函式庫(DLL),即程式在編譯時期並不會和這些函式庫連結,而是等到執行期間才會呼叫這函式。

Socket API in the OSI and TCP/IP models
Socket API
每個網路應用程式都有一個通訊端點,一種端點是用戶端(Client),另一種是伺服器(Server)。根據定義,用戶端會先送出第一個封包,由一個伺服器接收。在初步接觸後,用戶端和伺服器均能開始收送資料。


Flow diagram for TCP sockets

所有的網路應用程式皆可分為五個步驟:
  1. 開啟一個 Socket (Open)
  2. Socket 命名 (Bind)
  3. 與另一個 Socket 結合 (Connect)
  4. Sockets 間收送資料 (Send/Receive)
  5. 關閉 Socket (Close)
TCP Client Server Socket Connection
WinSock BSD Socket API 的函式庫:
WinSock Extended API
BSD Socket API
Description
WSAAccept
accept
accept 的延伸WinSock API
listening 的伺服端 Socket 接受來自remote Socket 的連結請求,並且建立Socket 連結。
WSASelect
select
select 的延伸WinSock API
設定Socket 的讀、寫狀態的I/O 傳輸。
WSAConnect
connect
connect 的延伸WinSock API
建立Socket 之間的連線。
WSARecv
recv
recv 的延伸WinSock API
接收來自另一Socket 所傳送的資料。
WSARecvFrom
recvfrom
recvfrom 的延伸WinSock API
接收來自另一Socket 所傳送的資料並且回傳此Socket 資訊。
WSASend
send
send 的延伸WinSock API
傳送資料至另一Socket
WSASendTo
sendto
sendto 的延伸WinSock API
傳送資料至指定IP 位址及通訊埠。
WSASocket
socket
socket 的延伸WinSock API
建立Socket

參考網頁
Wikipedia – Network socket
Wikipedia – Berkeley sockets
◎ Wikipedia – Winsock 

2013429 天氣報告
氣溫:25.2 @ 22:20
相對濕度:百分之95%
天氣:微雨

2013年4月28日 星期日

DIY - 智能小車:Microsoft Visual C++/CLI 介紹 (二十五)

DIY - 智能小車:Microsoft Visual C++/CLI 介紹 (二十五)

筆者已往都是使用 C/Visual C++ 的語言來編寫程式,雖然仍是不能夠完全掌握,一般編寫 C 程式是需要時間來獲得知識和經驗,在測試 S605 Webcam 使用了 C# 來編程,感覺 C# 加上 .NET 的簡單直接而強大,雖然 C# 語言就比較陌生,但 .NET Framwork 是非常好的框架,所以考慮使用新的 C++/CLI 來編寫程式。

Microsoft Visual C++/CLI
C++/CLI CLICommon Language Infrastructure,通用語言框架)是一門用來代替 C++ 託管擴展新的語言規範,C++ 是電腦程式設計語言,它是一種靜態資料類型檢查的,支援多範型的通用程式設計語言。CLI 提供了一套可執行代碼和它所運行需要的虛擬執行環境的規範。CLI 是作為作業系統和應用程式中間的抽象層,簡單而言 C++/CLI 除了包含 C++ 和  CLI 擴展,最重要是C++ .NET 的無縫連接,就是將新與舊的東西結合在一起。


2003106,歐洲電腦製造商協會(ECMAEuropean Computer Manufacturers Association)宣佈成立專家組,負責結合 ISO 標準 C++ 與通用語言,開發一個可擴展語言的標準,這個新的可擴展語言被稱為 C++/CLI 標準。C++/CLI 現在可以被 Visual C++ 2005 和更高版本的編譯器支援。C++/CLI 的部分特性已經申請了專利。

ECMA Logo

C# C++/CLI 的語法:
Items
C#
C++/CLI
Create a new object
object obj = new object();
Object^ obj = gcnew Object();
Create a strings
String s = "Hello";
String ^s = "Hello";
Create a integer
int len = s.Length;
int len = s->Length;
Create an array
int[] integers = {1, 2, 3, 4};
array^ integers = {1, 2, 3, 4};
Create an array
int[,] moreIntegers = { {5,6}, {7, 8} };
array^ moreIntegers = { {5,6}, {7, 8} };
Create an array
string[] strings = new string[2]{"Hello", "World"};
array^ strings = gcnew array(2){"Hello", "World"};
Create a subroutine
static void RunFoo(Func foo)
void RunFoo(function foo)

Allocate on native heap

N* pn = new N;
Allocate on CLI heap

R^ hr = gcnew R;
Bind ordinary reference to native object

N& rn = *pn;
Bind tracking reference to gc-lvalue

R% rr = *hr;
Null
something = null;
something = nullptr;
Customer Cursor
This.Cursor
This->Cursor=gcnew System::Windows::Cursor::UpArrow


以上是主要 C++/CLI 語法,其實還有很多很多!暫不能完全了解

C# 程式:
// C#
using System;

enum Gender
{
    Male,
    Female
}

class Person
{
    public string Name;
    public int Age;
    public Gender Sex;

    public Person(string name, int age, Gender sex)
    {
        Name = name;
        Age = age;
        Sex = sex;
    }

    public override string ToString()
    {
        return String.Format("Name = {0, -10} Age = {1}  Sex = {2}", Name, Age, Sex.ToString()[0]);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Person[] persons = new Person[4];
        persons[0] = new Person("John", 25, Gender.Male);
        persons[1] = new Person("Freda", 35, Gender.Female);
        persons[2] = new Person("Bill", 45, Gender.Male);
        persons[3] = new Person("Danielle", 55, Gender.Female);
        foreach (Person person in persons) Console.WriteLine(person);
        Console.ReadKey();
    }
}

C++/CLI 程式:
// C++/CLI
// personlister.cpp : main project file.

#include "stdafx.h" // standard header

using namespace System;

enum class Gender
{
    Male,
    Female
};

ref class Person
{
public:
    String^ Name;
    int Age;
    Gender Sex;

    Person(String^ name, int age, Gender sex)
    {
        Name = name;
        Age = age;
        Sex = sex;
    }

    virtual String^ ToString() override
    {
        return String::Format("Name = {0, -10} Age = {1}  Sex = {2}", Name, Age, Sex.ToString()[0]);
    }
};

int main(array ^args)
{
    array^ persons = gcnew array(4);
    persons[0] = gcnew Person("John", 25, Gender::Male);
    persons[1] = gcnew Person("Freda", 35, Gender::Female);
    persons[2] = gcnew Person("Bill", 45, Gender::Male);
    persons[3] = gcnew Person("Danielle", 55, Gender::Female);
    for each (Person^ person in persons) Console::WriteLine(person);
    Console::ReadKey();
    return 0;
}

The output of both programs is:
Name = John Age = 25 Sex = M
Name = Freda Age = 35 Sex = F
Name = Bill Age = 45 Sex = M
Name = Danielle Age = 55 Sex = F

參考網址: 
 
2013428 天氣報告
氣溫:23.4 @ 21:50
相對濕度:百分之91%
天氣:微雨