10 februari, 2016

En fantastiskt bra bokningstjänst vid namn Boka365

Hej igen, bloggen har varit väldigt inaktiv då jag helt enkelt inte haft tid över att skriva nya inlägg och artiklar men det ska jag försöka börja med igen.

Artiklarna kommer fortfarande handla om IT generellt fast med mer fokus på programming, servrar och nätverk samt även ett bokningssystem jag utvärderar som heter Boka365.

Denna gången kommer jag inte skriva så mycket utan kommer istället nämna bokningstjänsten Boka365 och hur min utvärdering går framöver.

Vad är bokningssystemet Boka365 för något och vad erbjuder de?

Boka365 är en tidbokningstjänst jag fann i höstas när jag sökte ett bokningssystem för en hamnvaktkalender och även stuguthyrning. Bokadirekt verkade som ett bra system men de erbjöd inte riktigt vad jag var ute efter och att de verkade lite dyra. De är säkert kanonbra för de verksamheter de riktar sig mest till men för mig passade de inte så bra.

Boka365 och hamnvakt

Med bokningstjänsten jag fann så kan jag lägga in alla båtplatser för ett hamnvaktsystem jag utvecklar och sedan kan medlemmarna gå in i kalendern och se vilka tider som är lediga för vaktronden. När de hittar en ledig tid kan de enkelt boka den direkt via telefonen eller datorn.

Jag såg att de även erbjöd kortbetalningar och direktbetalningar via Payson och Paypal och det kan nog bli ovärderligt framöver när vi ska utöka systemet till att automatisk registrera medlemsavgifterna.

Jag kommer definitivt skriva mer om tjänsten när jag har utvärderat den lite mer. Just nu är det 14 dagar gratis demotid om du vill prova på och sedan har de fyra abonnemang att välja bland. Det billigaste alternativet kanske lämpar sig bäst för mindre föreningar men för att få kortbetalningen behöver du välja ett dyrare abonnemang. Men det verkar helt klart vara värt pengarna.

Läs mer om deras priser och abonnemang

Stuguthyrning

Om bokningstjänsten lämpar sig riktigt bra för bokningar så kanske min släkt kan börja använda tjänsten också för att hyra ut vår stuga i Värmland. Det återstår att se men det ser helt klart lovande ut.

Än så länge verkar boka365 vara fantastiskt bra för mina behov och jag kommer skriva mer om det framöver.

Ha en god dag.

04 maj, 2012

Utveckling: Regular Expression Tester

När jag programmerar använder jag reguljära uttryck ofta, som även kallas för Regular Expressions eller kort och gott Regex.

Om Regular Expressions
Jag tänker inte gå igenom hur det fungerar men om ni gärna vill veta så kan jag tipsa om Wikipedia som tyvärr är svårläst men innehåller mycket information http://en.wikipedia.org/wiki/Regular_expression och följande http://www.regular-expressions.info/tutorial.html En annan hemsida som är bra på att förklara detta är PHPs egna dokumentation som ni finner här http://www.php.net/manual/en/reference.pcre.pattern.syntax.php

Här är en av många hemsidor på Internet som erbjuder en testare online, direkt i webbläsaren, där du kan testa dina mönster (patterns), och snygg är den också jämfört med många andra sidor.

Testa regex online
http://www.onlineregularexpression.com

Give it a shot

24 april, 2012

Unix/Linux: Cron jobb med PHP CLI till logg med datum som filnamn

Tips:

Hur man skapar ett cronjobb på Unix/Linux med ett PHP-skript som körs som CLI kommando. Jag vill också att loggfilen sparas med dagens datum utan klockslag.

Observera att sökvägarna kan skilja för er i era miljöer.
  1. Skapa ett php skript som heter cron.php som gör något, t.ex uppdaterar cachade filer och spara den i /home/testuser/public_html/crontest/cron.php
  2. Ta reda på var binären för PHP finns
    $ whereis php
    /usr/local/bin/php
  3. Testkör skriptet och utdata skrivs till terminalen
    $ /usr/local/bin/php /home/testuser/public_html/crontest/cron.php
  4. Testa skriva ut dagens datum år månad datum
    $ date +"%y%m%d"
    120424
     
  5. Skapa en logg-katalog
    $ pwd
    /home/testuser/public_html/crontest

    $ mkdir log
     
  6. Kör skriptet igen men den här gången skickar vi utdata till en extern logg-fil.
    $ /usr/local/bin/php /home/testuser/public_html/crontest/cron.php >> /home/testuser/public_html/crontest/log/cron_`date +"\%y\%m\%d"`.log
     
  7. Lista loggar
    $ ls -latr log
    drwxr-xr-x 6 testuser testuser  4096 Apr 24 09:00 ../
    -rw-r--r-- 1 testuser testuser  1068 Apr 24 09:26 cron_120424.log
    drwxr-xr-x 2 testuser testuser  4096 Apr 24 09:26 ./
     
  8. Skriv ett cron-jobb med verktyget crontab
    # crontab -e
  9. Ange kommandot:
    30 7,12 * * 1-5 /usr/local/bin/php /home/testuser/public_html/crontest/cron.php >> /home/testuser/public_html/crontest/log/cron_`date +"\%y\%m\%d"`.log
  10. Det betyder att ett jobb kommer utföras varje måndag till fredag (1-5) kl 07.30 och 12.30, alla datum och månader. Mitt PHP-skript rensar cache och uppdaterar cache för ett system jag själv har utvecklat, och det behöver köras innan jag börjar varje vardagmorgon och under tiden jag har lunch.

    Smart va!?
  11. Tänk på att rensa de gamla filerna ibland i katalogen "log", vilket du också kan göra med ett cronjobb, för att hålla ordning och reda samt inte fylla disken med loggar som kan bli stora.
  12.  Om du vill kan du även lägga till aktuell timma i loggfilens namn för att få en separat logg för varje cronjobb om de körs exempelvis två gånger per dag vid olika timmar på dygnet.

    Testa följande:
    $ date +"%y%m%d%H"
    12042409

    Lägg bara in ändringen i kommandot som körs i crontab så är allt klart.
Felsökning?
Om du får problem och måste avbryta scriptet kan du kontrollera processen och kör sedan kill på processen PID.

$ ps -ef | grep php
$ kill -9

Loggen för cron-jobb brukar vara /var/log/cron och då är följande kommando bra att använda i ett extra terminalfönster under tiden som du arbetar och felsöker i ett annat:

$ tail -f /var/log/cron

Kolla gärna in stackoverflow också: http://stackoverflow.com/questions/2135478/how-to-simulate-the-environment-cron-executes-a-script-with

Förbättring
Efter att jag har kört lite har jag stött på miljö-problem i cron-miljön (cron environment). Till slut kom jag fram till att istället anropa skriptet som en hemsida och spara resultatet med wget.

Lägg bara in följande kommando i crontab så kommer det funka:
$  /usr/bin/wget -O cron_`date +"\%y\%m\%d\%H"`.log -P /home/testuser/public_html/crontest/tmp/ http://www.test.se/crontest/cron.php?passwd=lösenord-för-cron-jobb-här

.htaccess HTTP Authentication
 Om filen cron.php ligger i en katalog som är skyddad med HTTP Authentication i en .htaccess fil, så kan man tillåta åtkomst till filen cron.php utan att behöva ange användarnamn och lösenord. All annan åtkomst till andra filer i katalogen kräver användarnamn och lösenord.

 /crontest/.htaccess
 AuthType Basic
AuthName "Administration"
AuthUserFile /home/testuser/public_html/crontest/.htpasswd
Require valid-user
<Files "cron.php">
Satisfy any
</Files>



Tjao

31 januari, 2012

PHP: Solution: Access Websitepanel 1.2.0 Hosting API with PHP nusoap - AddUser error - Object reference not set to an instance of an object

Swedish/svenska
Notis: Denna artikel är skriven på engelska för att det är många utländska prorgrammerare som har problem med Websitepanel och dess API. Därför bestämde jag att skriva den på engelska, dels för att hjälpa mig själv och att dela med mig av kunskapen om hur jag löste problemet till alla som söker efter en lösning på problemet.


Some words about this article
I wrote this article/guide because I'm developing a PHP API for Websitepanel using NuSOAP instead of PHP SOAP extension, and I encountered big problems yesterday and this morning. I want to share my solution and show everyone how I solved it.

The problem
When you use PHP to add a new user with the API function AddUser in esUsers.asmx then most of you will encounter problems and get an error like the following:

Object reference not set to an instance of an object

I pulled my hair, I read the specification, I read examples, I googled for a solution but every solution I found was someone saying he/she solved it by switching to PHP's SOAP extension and not using NuSOAP, and they didn't even publish the solution in code. Why oh why. This made it even more difficult. And I'm not the kind of guy that asks questions i forums - I search before I ask.

Debugging
I tried to output NuSOAP debugging information but that was a smack in the face - too much information and it almost looks the same everywhere, and I don't know where to look. A bit further down in the output I saw some trail of what could be wrong, but I already knew that one parameter was not valid, because it was not working. So continuing with the documentation...

Documentation
What about the documentation for the API, you say? It's kind of incomplete and only has a small working example and including information about how to add a new user but not how to use it in code. The documentation only describes the parameters and their values.

Solution?
I found the solution and I could not believe it - it was so simple but at the same time very unclear and frustrating. I should also say that UserExists works without any problems.

Here is code that does not work and almost everyone that tried to solve this in forums on the Internet used the following code.

PHP:
$param = array(
'OwnerId' => "1", // Owner of the account
'RoleId' => "3", // User
'StatusId' => "1", // Active
'IsDemo' => "false",
'IsPeer' => "false",
'Username' => "testuser",
'Password' => "123456abc!",
'Firstname' => "Testfirst",
'Lastname' => "Testlast",
'Email' => "test@test.com",
);

// This code does NOT work!!
$wsp->call('AddUser', array('parameters' => $param),
'http://smbsaas/websitepanel/enterpriseserver',
'http://smbsaas/websitepanel/enterpriseserver/AddUser');
But then I read the specs one more time slowly and focusing on the documentation at the same time. Then I noticed what was wrong.

Here is the SOAP XML specification:
<s:element name="AddUser">
<s:complextype>
<s:sequence>
<s:element minoccurs="0" maxoccurs="1" name="user" type="tns:UserInfo">
<s:element minoccurs="1" maxoccurs="1" name="sendLetter" type="s:boolean">
</s:element></s:element></s:sequence>
</s:complextype>
</s:element>
Can you see that there are 2 named parameters called "user" and "sendLetter"? That means that the call to AddUser requires a multidimensional array, where the index named "user" shall be assigned the array that contains the user details.

In the documentation it says the following:
"All other fields of the 'user' parameter are optional.
Also you may decide to set 'sendLetter' parameter to 'true' if you would like to send user registration notification."

I first thought that the user details array also could include an index called sendLettter but now I know that it should be completly separate.

Ok, here is the solution
The following code does the trick :)

PHP:
$param = array(
'OwnerId' => "1", // Owner of the account
'RoleId' => "3", // User
'StatusId' => "1", // Active
'IsDemo' => "false",
'IsPeer' => "false",
'Username' => "testuser",
'Password' => "123456abc!",
'Firstname' => "Testfirst",
'Lastname' => "Testlast",
'Email' => "test@test.com",
);

// SOLUTION: Create multidimensional array as
// parameter to follow the SOAP XML specification
$user = array(
'user' => $param
// 'sendLetter' => true
);

// This code DOES work!!
$wsp->call('AddUser', array('parameters' => $user),
'http://smbsaas/websitepanel/enterpriseserver',
'http://smbsaas/websitepanel/enterpriseserver/AddUser');
Perfect!

In my Websitepanel Audit log I saw the following information:
Information 1/31/2012 9:19 AM 9:19 AM User Add test1 adminuser

I hope that you really get this working. And have a nice day

Happy programming

// Waschman

25 oktober, 2011

Utveckling: Notepad++ Länka till CHM PHP Manual

Här är ett tips, som jag fann precis nu, för er PHP-utvecklare som vill integrera PHP manualen in i välkända Notepad++.

Skapa ett nytt kommando i Notepad++ (engelsk version) på följande sätt:
  1. Tryck på knappen F5 för att öppna fönstret "Run"
  2. Klistra in följande text i rutan:

    hh.exe mk:@MSITStore:C:\manuals\php_enhanced_en.chm::/res/function.$(CURRENT_WORD).html

  3. Tryck på knappen "Save..." och välj vilka tangenter som skall aktivera genvägen. Jag valde t.ex CTRL+ALT+F10
  4. Det som händer är att jag kan markera en PHP funktion i koden jag redigerar för tillfället och kan då öppna den lokala PHP manualen genom att aktivera genvägen med tangentbordet.



Tips!
Detta kommando fungerar även på andra CHM-dokument för att skapa genvägar, men du måste ändra sökvägen.

20 oktober, 2011

Windows XP: Symboliska länkar / Symbolic links

Åh, jag fann precis ett underbart program till Windows XP som fungerar för er som har NTFS och som vill skapa symboliska länkar.

Det heter Junction, är utvecklad av Microsoft, och kan skapa en symbolisk länk (symbolic linc) [1]

När vill man använda detta? Jag använder det t.ex när jag vill säkerhetskopiera min iPad till en annan plats än den förkonfigurerade sökvägen inuti iTunes, vilket inte går att redigera.

iTunes vill spara alla säkerhetskopieringar till följande sökväg:
C:\Documents and Settings\\Application Data\Apple Computer\MobileSync\Backup

Men jag vill spara filerna här istället:
G:\ipad_backup

Då kan jag köra följande kommando i Windows XP:
C:\junction\> junction.exe "C:\Documents and Settings\\Application Data\Apple Computer\MobileSync\Backup" G:\ipad_backup -s

Nu fungerar det så att om iTunes kopierar filer till katalogen "Backup" så skickas de istället till katalogen "ipad_backup". Bra va!

I Windows Vista och Windows 7 finns det inbyggda kommandon för detta men jag har ännu inte provat själv.

Referenser
[1] http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx

04 oktober, 2011

Tutorial/Network: How to subnet a Class A IP Address (VLSM/CIDR)

Introduction
Hi everyone!
I am going to go through how to subnet a class A IP address network for CIDR. This is not going to be a tutorial for complete beginners but instead towards network technicians that are either studying or work with IT Networks and Communication.

Usually I write articles in Swedish but I thought that this would fit best in english because I think that more english-speaking people are trying to find solutions on this topic. This article is also written in memory for myself so I don't have to search through so many websites when I have this problem in the future.


The goal with this tutorial
Take one IP address network and create more smaller networks from that. This is good when we for example want to summarize addresses.

Take this IP network address: 28.32.0.0/11
We want 4 networks with prefix /14
and the results will be something like this:

Address. Prefix Subnetmask....... Range............Broadcast
28.32.0.0 /14 255.252.0.0 28.32.0.1 - 28.35.255.254 28.35.255.255
28.36.0.0 /14 255.252.0.0 28.36.0.1 - 28.39.255.254 28.39.255.255
28.40.0.0 /14 255.252.0.0 28.40.0.1 - 28.43.255.254 28.43.255.255
28.44.0.0 /14 255.252.0.0 28.44.0.1 - 28.47.255.254 28.47.255.255

Note:
Please not that this is not optimized for real networks. This is just an example and you have to adapt it to your situation and planning. But I think you can make it work.


Let's start
We have IP network address 28.32.0.0/11 and we want to create several subnetworks with prefix /14.

Let's calculate the subnetmask and binary for prefix 11 and 14:
Prefix /11: 255.224.0.0 => 11111111.11100000.00000000.00000000 (eleven 1s)
Prefix /14: 255.252.0.0 => 11111111.11111100. 00000000.00000000 (fourteen 1s)

The fourteen bits are the network bits and they are marked with red
The three bits marked with orange color are subnet bits.
The zeroes are host bits and they are marked with blue color.

Total number of hosts
To calculate the total number of hosts for each subnet we need to cound how many zeroes we have: 2 + 8 + 8 = 18

Then we can use a formula for the total number and the usable total number of hosts IP addresses.

Total number of hosts: 2^18 = 262144
Usable total number of hosts: 2^18 - 2 = 262142

Note:
We subtract two because we remove the network address and broadcast address for the assignable range of host IP addresses.


Calculate the subnet IP ranges
First we search for our increment, a value that helps us to verify the calculation later on. You find the increment by looking at the right most binary 1 in the subnetmask. Then you convert that binary 1 to its decimal equivalent.

Example
28.32 = 00011100.00100000
255.252 = 11111111.11111100

00000100 = 4

The increment is marked with green color. The increment is used to easier check that the ranges are correct. Every new subnet has incremented the octet by 4 when we calculate the range.

Remember this rule: We only change the zeroes and the subnet bits when calculating the ranges.

We start with subnet zero and I only show the second octet (28.32.0.0) because it's most important. The bits are marked with their respective colors to make it easier for you to follow. I only show the network address and the broadcast address for each subnet. The usable host IP addresses are contained within.

Subnet bits are orange
Host bits are blue
Network bits are red

Can you see the pattern? Please note that the network and broadcast addresses are incremented by 4 for each new subnet. 36-32 = 4
#0 00100000 - 00100011 (32-35)
#1 00100100 - 00100111 (36-39)
#2 00101000 - 00101011 (40-43) <-- See example below
#3 00101100 - 00101111 (44-47)
#4 00110000 - 00110011 (48-51)
... etc ...
Here is an example of subnet #2:

Network..First IP....Last IP.......Broadcast
28.40.0.0 28.40.0.1 - 28.43.255.254 28.43.255.255

Decimal.........Binary
28.40.0.0.... = 00011100.00101000.00000000.00000000
28.40.0.1.... = 00011100.00101000.00000000.00000001
28.43.255.254 = 00011100.00101011.11111111.11111110
28.43.255.255 = 00011100.00101011.11111111.11111111
And now we're done! At least we now have a table with numbers that we can expand further and assist us in our network design and planning phase.


Extra assignment ahead
Try to come up with an IP address that summarizes subnets #1 to #3?

Summarization is used mostly in routers to reduce the size if the routing tables and to reduce flapping routes; routes that changes, get added or get removed. If you summarize these routes, they will not be noticed futher down. This is especially useful in OSPF networks between areas to reduce memory and CPU processing. The core routers have summarized routes to surrounding areas.


Read here if you want the solution
28.36.0.0/12

How did I come up with that? First I compared subnet #1, #2 and #3 to see what bits that were in common. The first four bits (0010) in the second octet were the same in all three subnets.

Then I calculate the new subnetmask prefix value for that octect, which is obviously 4, and then adding 8 from the first octet. 8+4 = 12. That's because I only want to use the subnetmask that includes these four bits that were same.

At last I just take the value of the octet from subnet number #1 and we have the final IP network address.

Have a nice day!

02 mars, 2011

MySQL: InnoDB Foreign keys och Cascade

Förord
Hej på er! Nu ska jag förklara lite mer om databasen MySQL och en av databasmotorerna InnoDB. Jag upptäckte igår vad detta innebär och då började jag komma ihåg att jag hade läst om detta förut i en bra bok om just MySQL databashantering. Boken heter "MySQL handboken : [den snabba vägen till grunderna i MySQL]" och passar utmärkt till den som vill lära sig MySQL och gå in lite mer på djupet.

När jag läste boken förstod jag inte så mycket om foreign keys, som på svenska heter "främmande nycklar", men det förstår jag bättre nu. Därför har jag tänkt att visa ett exempel på när det kan vara mycket användbart.

Mycket bra läsning på engelska finns i en artikel publicerad på InnoDB.com [2]

Introduktion
Vad är MySQL?
Okej, som de flesta vet så är MySQL en typ av databas där man kan lagra information på ett strukturerat sätt. Och för er som inte vet, så vet ni nu vad MySQL är för något.,

SQL = Structured Query Language

Men vad kan MySQL användas till?
MySQL använder s.k. SQL-frågor för att skicka och hämta data från en databas. MySQL kan användas till att lagra information strukturerat om t.ex kunder som har bokat klipptider hos en frisör, eller produkter och artiklar som man vill sälja via en hemsida. När någon sedan har lagt en beställning kan man koppla produkterna till en specifik beställning som i sin tur hör till en registrerad kund.

Ett vanligt exempel från gymnasiet är en databas med elever som kommer att börja på skolan nästkommande termin. Vi fick lära oss hur man designar en databas med tabeller som är relaterade till varandra och hur man endast kan tillåta unika personer i databasen baserat på unika personnummer.

Fint, men vad är InnoDB för något?
I MySQL används olika databasmotorer (engines) för att spara och hämta data på olika sätt. Ska datans integritet kontrolleras eller spelar det ingen roll? Ska tabeller relateras med varandra eller skötas med programmering? Det är uppgiften som en databasmotor har.

InnoDB är inte så vanlig bland nybörjare eftersom standardmotorn heter MyISAM och många vet inte eller bryr sig inte om att kontrollera vilken databasmotor man använder. Databasen funkar ju fortfarande på samma sätt, eller? Ja det är sant men InnoDB kan kontrollera data i databasens tabeller så att länkarna, relationerna och integriteten inte bryts om en ändring sker i databasen.

Huvudregeln säger att i en relationsdatabas (en databas med relationer vilket hörs på namnet) så måste relaterade nycklar ha en korrekt länkning - nyckel1 med ID 4 i tabell A måste vara samma som nyckel1 med ID 4 i tabell B. Med InnoDB kan man kontrollera att ID-numret måste vara samma i båda tabellerna som är relaterade med varandra genom användning av främmande nycklar.

Om du inte förstår så är det helt förståeligt. Det kan vara ett svårt koncept i början innan man lär sig. Jag kommer strax gå igenom skillnaderna mellan InnoDB och MyISAM (den vanligaste databasmotorn).


Först en kort beskrivning om primärnycklar och främmande nycklar
En primärnyckel måste vara unik i en tabell. Dubbletter och kopior får inte förekomma. Ett vanligt exempel på en primärnyckel är ett ID i en tabell som automatiskt räknar uppåt när nya rader med data läggs till. Om man ska ha ett personnummer i en databas så passar personnumret utmärkt som en primärnyckel eftersom det ska vara unikt. Detta är bra så att man inte råkar fylla i ett som redan finns.


När ska man använda InnoDB och MyISAM?
Kortfattat
Om du har en t.ex en hemsida med en databas som innehåller en tabell som kommer att uppdateras och ändras kontinuerligt och väldigt ofta, då passar InnoDB. Speciellt om du har flera tabeller som är relaterade till varandra. Då kan InnoDB säga till när det blir fel och hjälpa till med uppdatering i andra tabeller. InnoDB är långsammare när det gäller SELECT och ändringar.

MyISAM ska man helst använda om det sällan sker INSERT, UPDATE och DELETE i tabellerna. Alltså om det sker mycket SELECT. MyISAM är snabbast men är också enklast att arbeta med.


Det bästa scenariot är...
Om man kan köra två databaser som master och slave med replikering. Då kan en av dem innehålla tabeller med InnoDB som håller koll på all integritet, och den andra har kopior av alla tabeller från den första fast med MyISAM istället för InnoDB. När data ska hämtas så anropas den andra med MyISAM. När data ska läggas till, uppdateras eller tas bort så anropas den första. Då får man det bästa av två världar - nja två olika tekniker i alla fall.


Nu ett exempel med InnoDB

Exempel 1
Beskrivning: Vi kommer ha en tabell där vi lagrar information om kategorier för produkter som säljs på en hemsida. Observera att detta exempel inte kommer fungera med MyISAM.

Skapa först en databas. Skapa sedan nedanstående tabeller.

CREATE TABLE tbl_products(
product_id INT UNSIGNED NOT NULL,
product_name VARCHAR(20),
PRIMARY KEY(product_id)
) ENGINE=InnoDB;
Detta är tabellen med produkter som sedan ska kopplas till kategorier.


CREATE TABLE tbl_categories(
category_id INT UNSIGNED NOT NULL,
category_name VARCHAR(20),
PRIMARY KEY(category_id)
) ENGINE=InnoDB;
Detta är tabellen med kategorier. Tabellerna ovanför beskriver inte hur de är relaterade med varandra. För det behöver vi ännu en tabell.

CREATE TABLE tbl_categories_products(
category_id INT UNSIGNED NOT NULL,
product_id INT UNSIGNED NOT NULL,
PRIMARY KEY(product_id, category_id),
FOREIGN KEY (category_id) REFERENCES tbl_categories(category_id),
FOREIGN KEY (product_id) REFERENCES tbl_products(product_id)
) ENGINE=InnoDB;


Nu kan vi se på bilden här nedanför hur relationen mellan tabellerna ser ut.

(Bild 1) Relation mellan tabeller produkter och kategorier

Lägga till lite data till tabellerna. Här lägger vi till några produkter:
INSERT INTO tbl_products(product_id, product_name)
VALUES
(1, 'MP3 spelare'),
(2, 'iPod'),
(3, 'iPad'),
(4, 'Dell Dimension 1111 PC'),
(5, 'PHP och MySQL Handboken'),
(6, 'Bäverdalen'),
(7, 'Samsung Galaxy Tab')


Lägg till några kategorier för produkterna:
INSERT INTO tbl_categories(category_id, category_name)
VALUES
(1, 'Musikspelare'),
(2, 'Läsplattor'),
(3, 'PC'),
(4, 'Böcker')


Skapa relationer mellan kategorier och produkter:
INSERT INTO tbl_categories_products(category_id, product_id)
VALUES
(1, 1),
(1, 2),
(2, 3),
(3, 4),
(4, 5),
(4, 6),
(2, 7)


Försök att lista ut själv hur relationen är uppbyggd. Första kolumnen är vilken kategori som den andra kolumnen tillhör. T.ex "PHP och MySQL Handboken" tillhör kategori nr 4 vilket är "Böcker".

Resultat
Nu måste utvecklaren och alla mjukvaror som tänker använda tabellerna tänka på att kontrollera integriteten själva genom att uppdatera alla tabeller som ändras för varje SQL-fråga till databasen. ID numren måste stämma överens annars får man ett felmeddelande av databasen. Så om jag nu skulle råka fylla i data (en post) i tabellen tbl_categories_products med följande SQL-fråga, så skulle jag få ett felmeddelande eftersom kategori ID-numret inte finns i tabellen tbl_categories.

INSERT INTO tbl_categories_products(category_id, product_id) VALUES (8, 2)



Exempel för MyISAM
Tyvärr har jag inte några exempel för tabeller som har MyISAM men jag vet att det fungerar genom att skapa sk Triggers. Läs gärna referensen [1] för att läsa mer.


Vad händer om man vill ändra ett ID-nummer i tabellen för kategorier?
Då blir det fel. Man måste ändra i båda tabellerna samtidigt har jag för mig. Men det problemet kan vi lösa i kommande text och exempel.


Cascade för "delete" och "update"
Med nyckelordet "Cascade" kan man tillåta att InnoDB själv ska ha kontroll över alla tabellerna automatiskt. Säg nu att jag vill byta ut ID-numret för kategorin "Läsplattor" till ID 17, då kan jag uppdatera numret för category_id i tabellen tbl_categories och ändringen sker även automatiskt i tabellen tbl_categories_products eftersom den är relaterad till category_id och måste vara likadan. Ändras en tabell så måste den andra tabellen också ändras.

Detsamma gäller när en rad tas bort. Om jag känner för att ta bort hela kategorin "Böcker" (ID nr 4) så kommer raden/raderna i tabellen tbl_categories_products med category_id = 4 att också tas bort.

Hur gör man då detta... man kan använda Cascade när man skapar en främmande nyckel. Nu kommer jag visa med ett exempel hur man gör. Man kan använda CREATE TABLE och ALTER TABLE för att ändra i efterhand. Jag kommer visa hur man gör via CREATE TABLE.

CREATE TABLE tbl_categories_products(
category_id INT UNSIGNED NOT NULL,
product_id INT UNSIGNED NOT NULL,
PRIMARY KEY(product_id, category_id),
FOREIGN KEY (category_id) REFERENCES tbl_categories(category_id) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES tbl_products(product_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB;


Detta betyder nu att tabellen övervakar de främmande nycklarna i de främmande tabellerna tbl_categories och tbl_products.

Om du nu testar att köra följande SQL-fråga så kan du se att två tabeller uppdateras. Den ena som du valde och den andra som har en relation med den du valde.

UPDATE tbl_categories SET category_id = 14 WHERE category_id = 2

Kontrollera tabellerna

SELECT * FROM tbl_categories
SELECT * FROM tbl_products
SELECT * FROM tbl_categories_products (har ändrat sitt category_id som var 2 automatiskt till 14)

Det borde se ut ungefär så här nu i tabellen tbl_categories:
+-------------+---------------+
| category_id | category_name |
+-------------+---------------+
| 1 | Musikspelare |
+-------------+---------------+
| 14 | Läsplattor |
+-------------+---------------+
| 3 | PC |
+-------------+---------------+
| 4 | Böcker |
+-------------+---------------+

tbl_categories_products:
+-------------+------------+
| category_id | product_id |
+-------------+------------+
| 1 | 1 |
+-------------+------------+
| 1 | 2 |
+-------------+------------+
| 14 | 3 |
+-------------+------------+
| 3 | 4 |
+-------------+------------+
| 4 | 5 |
+-------------+------------+
| 4 | 6 |
+-------------+------------+
| 14 | 7 |
+-------------+------------+


Slutsats
Slutsatsen med detta testet är att jag nu kommer överväga att använda InnoDB för mer kritiska applikationer där det sker många ändringar i databasen. Om jag kör detta system på en hemsida kommer jag att köra cachelagring av all data så behöver data bara hämtas en gång med SELECT från databasen och resten sparas i textfiler.

Det kommer också bli svårare att designa sin databas så jag får planera bättre i framtiden exakt vilka tabeller jag vill använda och hur man eventuellt kan uppdatera databasen i framtiden för att minska problem och fel så mycket som möjligt.

Nu behöver jag bara uppdatera en tabell och behöver inte tänka på vilka andra tabeller som är indirekt relaterade till tabellen genom "osynliga" relationer. Med detta menar jag att jag alltid innan har skrivit applikationer som själva måste hålla reda på att ändra i t.ex tabellen tbl_categories_products så fort jag uppdaterar ett kategori ID eller tar bort en kategori.

Ett bra scenario är kommentarer som är kopplade till ett blogginlägg. Tar man bort blogginlägget så ska alla tillhörande kommentarer tas bort automatiskt utan att jag som programmerare behöver tänkta på att skriva kod som måste utföra det manuellt. Nu sköts allt i databasen och koden blir mer abstract och enklare att underhålla.

Slutord
Det var allt för den här gången. Jag hoppas att artikeln har varit till någon nytta för er.

Mvh
Waschman


Referenser
[1] http://dev.mysql.com/tech-resources/articles/mysql-enforcing-foreign-keys.html
[2] http://blogs.innodb.com/wp/2010/09/mysql-5-5-innodb-as-default-storage-engine/

10 februari, 2011

jQuery: Ny version 1.5 av jQuery men bug om man använder jQuery UI 1.8.9

jQuery version 1.5 släpptes för några dagar sedan men redan har jag hittat ett fel, vilket är ganska allvarligt. Versionen blockerar kod som använder sortable och draggable i paketet jQuery UI om de är anslutna till varandra (connectedWith)

Ni kan läsa mer på detta foruminlägg: http://forum.jquery.com/topic/weird-weird-error-on-draggable

Följande kod kommer alltså inte att fungera i nuläget om ni använder version 1.5:
$('.cms-block-container').addClass('cms-sortable');
$('.cms-sortable').sortable({
appendTo: 'body',
connectWith: '.cms-sortable',
revert: true,
placeholder: 'sortable-placeholder',
delay: 300,
opacity: 0.75,
handle: '.cms-block-move-handle',
cancel: '.cms-drop-zone-placeholder',
helper: function(event) {
return $('sortable-html-code-here');
},
... and activate, deactivate etc.


$('.cms-draggable').draggable({
appendTo: 'body',
connectToSortable: '.cms-block-container',
helper: 'clone',
cursor: 'move',
opacity: 0.75,
cursorAt: { left: -3, top: -3},
helper: function(event) {
return $('sortable-html-code-here');
}
}).disableSelection();

Lösningen på problemet är att använda en tidigare version, v.1.4.4 är bekräftad och fungerar.

Detta är varför jag inte använder skript som heter latest.js när man infogar kod från exempelvis googlecode.

04 augusti, 2010

XHTML/Javascript: Ej blockerad nedladdning och optimering av websida när Javascript och CSS används

English title: Non-Blocking download and optimization of webpages when using Javascript and CSS

Förord
Är du webbutvecklare/webbdesigner som vill att din websida ska ladda snabbare? Använder du skript som tar lång tid att ladda? Då kanske du finner din lösning här. Fortsätt läs för att få veta mer.


Introduktion
När en webbsida laddas i en webbläsare skickas det ett anrop för varje skript, stilmal och bild som existerar i koden för webbsidan. När skript och stora stilmallar måste hämtas och läsas in tar det tid. Detta blockerar webbläsaren från att fortsätta tills nedladdningen av filerna är klara. Om man då har ett stort skript som måste laddas in först, börjar text och bilder inte synas förrän den har laddat klart.

Lösningen? Komprimera skript och stilmallar för att minska på filstorleken och försök få allt att laddas ned samtidigt. Försök också att ha så får anrop som möjligt. Webbläsarna använder mestadels GET- och POST-anrop och de bör hållas till ett minimum.

Tipsen i denna artikel kan även användas på webbsidor anpassade för mobiltelefoner och t.ex iPad, som är begränsade till hastigheter inom GSM/GPRS/3G/4G som varierar mycket beroende på var man befinner sig geografiskt. De har även i många fall sämre RAM och CPU-kraft som krävs för att rendera webbsidor. Färre anrop förbättrar upplevelsen.


Tester
Jag har utfört tre tester på min egna webbsida med följande uppsättning:
  • Firefox 3.6.8
  • Firebug 1.5.4
  • PHP (957 b)
  • XHTML Strict
  • CSS (883 kB)
  • Javascript (310 kB)
  • Stor bild (2.7 MB)

Att tänka på innan man börjar
Javascript brukar vara stora och ta upp mycket utrymme samt ha tunga beräkningar. Se till att komprimera alla skript så de tar upp så lite utrymme som möjligt. Då går det snabbare att ladda in dem.

Min fil med Javascript är bara komprimerad till hälften och innehåller många olika skript och bibliotek som har infogats i en enda fil istället för att använda flera.

Istället för:
<script type="text/javascript" src="skript1.js"></script>
<script type="text/javascript" src="skript2.js"></script>
<script type="text/javascript" src="skript3.js"></script>
<script type="text/javascript" src="skript4.js"></script>
<script type="text/javascript" src="skript5.js"></script>

Använder jag:
<script type="text/javascript" src="alla_skript.js"></script>

Detsamma gäller också för alla mina stilmallar. Använd inte "@import" i CSS för att ladda in externa stilmallar. Det skapar extra anrop i vissa webbläsare. Ni bör avstå från det. Det bästa är att sammanfoga alla stilmallar till en enda stilmall.


Komprimering
Många webbapplikationer, webbtjänster och skript erbjuder möjligheten att komprimera (minska) filernas storlek. Här är ett exempel på en sökning

För er som vill testa på att komprimera skript med PHP kan läsa följande artikel http://www.devirtuoso.com/2009/07/how-to-compress-cssjavascript-files-with-php/


Laddningstider och blockering av laddning
http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/ är en av de bästa artiklarna jag har läst som beskriver vad ämnet handlar om och vad man kan använda för att lösa problemen.

En lösning som jag har börjat använda är enkel att använda och effektiv. Metoden kallas "Script DOM Element" och går ut på att man med hjälp av lite Javascript, inuti head-sektionen på en webbsida, kan skapa en skript-tagg dynamiskt när webbsidan börjar laddas. Man anger att källan (eng. source, xhtml. src) ska peka mot skriptfilen.

Då skapar man parallell nedladdning i webbläsaren, det vill säga att skriptet laddas ned samtidigt som resten av sidan.

Viktigt! Lösningen med "Script DOM Element" varierar mellan olika webbläsare och jag rekommenderar att ni läser artikeln jag nämnde ovanför och tar en titt på bilden här http://stevesouders.com/efws/images/0405-load-scripts-decision-tree-04.gif Det har att göra med om skriptet ligger på samma domän som webbsidan eller inte, samt om inbäddade skript är beroende av skriptet eller inte.


Förklaring av mitt test
Jag utförde tre tester i webbläsaren Firefox version 3.6.8 och till min hjälp använde jag Firebug version 1.5.4 för att ta tid och för eventuell felsökning. I Firebug kan man se fina grafer över nedladdningen av webbsidan. Man kan se vilka delar i koden som tar längst respektive kortast tid att utföra. Mer information om tester hittar ni under rubriken Scenario.

Exempel på graf i Firebug

(Klicka på bilden för att förstora)

I graferna kan man se vilket svar man fick från webbservern (Response, GET, POST, 404, 200, 304, m.fl) samt tiden. Det bästa är om stilmallar, skript och bilder kan laddas ned parallellt (samtidigt).

Viktigt
Innan varje test utförs måste man rensa webbläsarens cache och Internetfiler för den aktuella dagen. Annars får man cachade filer vilket ger ett vilseledande resultat. I Firefox görs det via menyn:
  1. Verktyg
  2. Rensa ut tidigare historik
  3. Välj Idag
  4. Kryssa för Besökta sidor och filhämtningshistorik samt Cache.



Så glöm inte rensa webbläsarens cache!!

Testerna påverkas även av din Internethastighet. En annan notering är att kommentarerna i min kod i testet är på engelska för att hjälpa engelska besökare som läser artikeln.


Scenario
Preparera en webbsida med lite text, en stor bild som helst ska vara minst 1MB, en stor stilmall och ett stort Javascript. Då ser man skillnanden tydligt och millisekunder är svårt att mäta eftersom det kan skilja ganska många från test till test. Ni kan referera till min kod som jag visar under testerna här nedanför.

I vanliga fall laddas objekten och resurserna i följande ordning.
  1. CSS och Javascript laddas parallellt
  2. Bilder laddas sist, ibland även text.
Men som jag sagt tidigare i artikeln, blockerar oftast Javascriptet resten av webbsidan från att börja ladda.


Test 1
En vanlig implementation av en webbsida.

Följande kod användes i testet:
<?php
//
// Test 1
// File: test.php
//
header("Cache-Control: no-cache");
header("Pragma: no-cache");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Testa laddning av Javascript</title>
<link rel="stylesheet" type="text/css" media="all" href="css2.css" />
<script type="text/javascript" src="javascript2.php"></script>
</head>
<body>
<p>Text som visas på hemsidan snabbt.</p>
<p><img src="stor_bild.jpg" alt="stor bild" width="700" /></p>
<p>Sista texten</p>
</body>
</html>

Resultat - Test 1

(Klicka på bilden för att förstora och se resultatet)

Beskrivning av resultatet
Vi ser att stilmallen och Javascriptet laddas parallellt medan bilden laddas senare (sist). På vissa webbsidor kan skripten vara sega och då tar det längre tid för hela webbsidan att laddas. Detta vill vi ändra på.


Test 2
Nu använder vi tekniken "Script DOM Element" för både stilmallen och Javascriptet. Tänk på att även använda taggen "noscript" om en besökare har en webbläsare med Javascript avstängt. Då måste de fortfarande kunna använda stilmallen som annars slutar fungera eftersom den inte kan laddas korrekt.

Följande kod användes i testet:
<?php
//
// Test 2
// File: test2.php
//
header("Cache-Control: no-cache");
header("Pragma: no-cache");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />

<title>Testa laddning av Javascript</title>
<noscript>
<link rel="stylesheet" type="text/css" media="all" href="css2.css" />
</noscript>
<script type="text/javascript">
/* <![CDATA[ */

// If you are using both CSS and JS DOM load, then you need to put the CSS link also inside a noscript tag

// CSS
var domscript_css = document.createElement('link');
domscript_css.rel = "stylesheet";
domscript_css.type = "text/css";
domscript_css.media = "all";
domscript_css.href = "css2.css";
document.getElementsByTagName('head')[0].appendChild(domscript_css);

// Javascripts
var domscript = document.createElement('script');
domscript.type = "text/javascript";
domscript.src = "javascript2.php";// Contains all Javascript
document.getElementsByTagName('head')[0].appendChild(domscript);
/* ]]> */

</script>
</head>
<body>
<p>Text som visas på hemsidan snabbt.</p>
<p><img src="stor_bild.jpg" alt="stor bild" width="700" /></p>

<p>Sista texten</p>
</body>
</html>

Resultat - Test 2


(Klicka på bilden för att förstora och se resultatet)

Beskrivning av resultatet
Nu ser vi att hela webbsidan laddas samtidigt och stilmallen och Javascriptet laddas ned parallellt. Detta kallas på engelska för "Non-Blocking Javascript" eftersom det gör att resten av webbsidan inte blockeras. Notera att det bara tar så lång tid det tar att läsa in filen test2.php och bilden. Vi har just nu minskat våra laddningstider med en hel sekund (1 sekund) om vi jämför med föregående Test 1.


Test 3
I det sista testet länkar jag till stilmallen precis som vanligt men Javascriptet laddas in dynamiskt. Ett tips är att alltid ladda in stilmallar innan skript.

Följande kod användes i testet:
<?php
//
// Test 3
// File: test3.php
//
header("Cache-Control: no-cache");
header("Pragma: no-cache");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Testa laddning av Javascript</title>
<link rel="stylesheet" type="text/css" media="all" href="css2.css" />
<script type="text/javascript">
/* <![CDATA[ */

// Javascripts
var domscript = document.createElement('script');
domscript.type = "text/javascript";
domscript.src = "javascript2.php";// Contains all Javascript
document.getElementsByTagName('head')[0].appendChild(domscript);
/* ]]> */

</script>
</head>
<body>
<p>Text som visas på hemsidan snabbt.</p>
<p><img src="stor_bild.jpg" alt="stor bild" width="700" /></p>

<p>Sista texten</p>
</body>
</html>

Resultat - Test 3

(Klicka på bilden för att förstora och se resultatet)

Beskrivning av resultatet
I det sista testet var det stilmallen som tog tid att ladda in och blockerar därför resten av webbsidan.


Analys
Testen visade tydligt vilken skillnad det var om man använde tekniken eller inte, eller om man blandade tekniken med vanlig kodning. Tiderna i resultaten kan variera men ni får gärna räkna ut ett genomsnittlig tid för varje test och sedan jämföra dem.

Nu testade jag med en extremt liten webbsida med endast två stycken och en bild. Stilmallen lästes in men användes inte på webbsidan. Om man testar med en större webbsida, tror jag man får bättre resultat och man upptäcker nog även enklare eventuella prestandaförbättringar.

Kontrollera även cache mm
Om det tar tid att ladda in koden skriven i HTML/XHTML varje gång en sida laddas, ska man tänka på följande:
  • Hämtas data från ren HTML?
  • Hämtas data från en databas (XML, MySQL, MS Access, MS SQL Server, ...)?
  • Används cache på servern?
  • Används cache på klienten?
  • Hur länge är ett objekt eller en resurs cachad?
  • Är data komprimerat eller i klartext?
  • Är data krypterad (ex. HTTPS, CHAP)?
Cachad data hjälper till att öka prestandan oerhört mycket och det märks tydligt på användningen av minne och processor på servern. Kryptering och omkodning av data kan också ta tid. Komprimera data om det är möjligt.

Snabbt om data redan finns i cache
Testerna visade att det bara tog några millisekunder att ladda webbsidan om man glömde rensa cache och Internetfiler innan man utförde varje test.

Tänk på antalet besökare
Om man inte har så många skript tror jag inte man behöver tänka på detta, men då måste man istället tänka på hur många besökare som besöker webbsidan. Om väntetiden är för lång när man laddar en webbsida (absolut max 10 sekunder enligt vissa rapporter) förlorar man besökare. För många företag betyder det förlust i intäkter och mindre pengar.

Låsning och blockering
Om ett skript låser sig i en evig loop eller om skriptet måste beräkna tunga data innan webbsidan laddas, blockeras resten av innehållet.

Kommer det fungera på din webbsida?
Kontrollera först noga om metoden ovan i testerna kommer fungera på just din webbsida eller i ditt scenario. Det finns vissa begränsningar som beskrivs i de andra artiklarna jag länkade till.

Testat i andra webbläsare?
Testerna har endast utförts i Firefox för att jag inte har haft tillgång till andra webbläsare, utom Internet Explorer. Jag vet inte riktigt om det finns något insticksprogram tillInternet Explorer


Slutsats
Min slutsats av testerna och analysen är att man först måste tänka på om det lönar sig att använda metoden. Metoden fungerar bra och jag kommer använda den när jag utvecklar mina webbapplikationer.

Lycka till

24 mars, 2010

PHP/MySQL: Konvertera från datetime till sekunder från epoch

English translation:MySQL and PHP Convert datetime to seconds

Undrar du hur man kan omvandla data från en kolumn i MySQL med datetime som datatyp till antalet sekunder från "epoch" (1970-01-01)? Det undrade jag och nu tänker jag dela med mig av lösningen.

Jag gillar att programmera med PHP och utveckla dynamiska hemsidor tillsammans med MySQL som backbone. Just nu för en liten stund sedan letade jag efter en lösning för att omvandla datetime till sekunder för att enklare formatera datum med PHP funktionen date().

Notis:
Jag vet att det finns utmärkta lösningar inbyggda i MySQL men i koden jag använder nu går det inte att lösa på det sättet. Det datum som returneras från databasen är alltid i formatet yy-mm-dd tt:mm:ss

<?php
echo strtotime('2010-03-24 12:26:00') .'<br/>';
echo strtotime('2010-03-24 12:27:00') .'<br/>';

// Resultat
// 1269458760
// 1269458820

// Verifiera att det fungerar
echo date('Y-m-d H:i:s', strtotime('2010-03-24 12:27:00') ) .'<br/>';

// Resultat
// 2010-03-24 12:27:00

// Ett annat format
echo date('l F j, Y, G:i', strtotime('2010-03-24 12:27:00'));

// Resultat
// Wednesday March 24, 2010, 12:27
?>

Men för er som verkligen vill lösa det på MySQL-viset kommer här ett exempel:

// Skriver ut 1269458820
SELECT UNIX_TIMESTAMP('2010-03-24 12:27:00')

Ganska enkelt eller hur? Vill ni veta mer om funktionen strtotime() [1] i PHP så hittar ni information i den grymma dokumentationen på www.php.net [2]

Lycka till med programmeringen

Referenser
[1] www.php.net/manual/en/function.strtotime.php
[2] www.php.net

10 mars, 2010

Nätverk: ARP - Address Resolution Protocol i datanätverk

Hej!

För er som undrar över hur kommunikation fungerar i ett nätverk mellan två enheter (t.ex två datorer) genom en switch och router kan ni läsa mitt svar här nedanför som jag gav till en utländsk student vid Halmstad högskola som jag hade i kursen IP-telefoni och trådlösa nätverk när jag var kursansvarig. Texten är på engelska. Om jag får in några kommentarer som vill ha en svensk översättning så fixar jag det.

Studenten frågade efter hur en PC känner till sin destinations IP-adress och hur datapaketen tar sig dit, utan att man specificerar subnätmasken i ICMP (ping) meddelandet. Allt har att göra med protokollet ARP - Address Resolution Protocol.

Till min hjälp har jag använt programmet Packet Tracer 5.2 för att felsöka kommunikationen. Jag har även bifogat en simpel topologi över nätverket.

--------------------------


(Klicka på bilden för att förstora)
--------------------------

Question: How does a PC know about the destination IP-address and how to get to it without sending the subnetmask in the ICMP (ping) message?

Answer:
Hi,
I tried a scenario in Packet Tracer just now and here it how it works.
  1. I choose to ping from 192.168.1.10 to 192.168.1.11
  2. ARP constructs a request for target IP-address 192.168.1.11, and sets the broadcast MAC-address to FF:FF:FF:FF:FF:FF
  3. ARP encapsulates PDU into Ethernet frame
  4. Frame goes to switch on the wire
  5. Switch receives frame on port fa0/2
  6. Switch processes frame up to OSi layer 2 "Data link"
  7. It is a broadcast (FF:FF:FF:FF:FF:FF), send out on all switch ports except the receiving port, so this is sending packets to router (192.168.1.1) and PC (192.168.1.11)
  8. Packets are sent out fa0/1 and fa0/3
  9. Router receives ARP request on port fa0/0
  10. The ARP request's target IP address does not match the receiving port's IP address, (192.168.1.11 is not matching routers IP of 192.168.1.1)
  11. The ARP process on the router checks the routing table whether the requested IP address is reachable, and the IP-address is reachable on source port fa0/0

    Router# show ip route
    C 192.168.1.0/24 is directly connected, FastEthernet0/0
    C 192.168.2.0/24 is directly connected, FastEthernet0/1

  12. ARP table on router is updated with souce IP-address (192.168.1.10) and MAC-address
  13. Router discards ARP-request
  14. Now the destination PC receives the ARP request on its ethernet port from the switch as a broadcast (FF:FF:FF:FF:FF:FF)
  15. The ARP request's target IP address matches the receiving port's IP address. (192.168.1.11 is matching 192.168.1.11)
  16. ARP-process on destination PC updates the ARP-table.
  17. ARP-process on destination PC replies to source PC with source port MAC-address, and encapsulates PDU into ethernet frame.
  18. Switch port fa0/3 receives request and looks in its ARP-table.
  19. The frame source MAC-address was found in its ARP-table.
  20. This is a uniucast frame (from PC 192.168.1.11 to PC 192.168.1.10) so switch looks in ARP-table for destination MAC-address
  21. Switch is sending unicast reply out fa0/2 port
  22. PC 192.168.1.10 receives ARP-reply on ethernet port and does now know about the PC 192.168.1.11 MAC-address on OSI layer 2
  23. It saves the information (mapping) MAC-address to IP-address.
  24. PC 0 can now send an ICMP (ping) message to PC 1 using only IP-addresses on OSI layer 3 "Network".

Now, if the ping is going to IP-address 192.168.2.10, then the ICMP-message will reach the router (which MAC-address is also in PC A's ARP-table). The router will check the routing table for destination IP-address network, if it's reachable. It is reachable through port router's fa0/1 to network 192.168.2.0/24

Then the ARP-process will start all over again on the other side, so the router will ask the switch, which in turn will broadcast the ARP out all switchports except receiving port (fa0/1). The request is going out fa0/2 to PC 2 with IP 192.168.2.10 and the IP is correct. An ARP-reply is then sent back to the router. ICMP (ping) can now continue.

I really recommend you to test Packet Tracer to look at TCP/IP and ARP messages going. You can also debug DHCP and some other protocols.

-----------------------------

Innan jag svarade studenten på hans fråga, trodde jag att jag kunde ARP, men efter en djupdykning i protokollet fick jag mer kunskap. Nu vet jag mycket bättre själv hur kommunikationen i ett datanätverk går till. Visst kunde jag detta utantill när jag studerande CCNA vid högskolan och gymnasiet men det är alltid bra att fräscha upp minnet lite.

Lycka till alla

26 december, 2009

God Jul och ett Gott Nytt År

Till er från mig önskar jag alla en god jul och ett gott nytt år.. eller man kanske ska säga god fortsättning denna Annandag Jul.

Jag jobbar mycket och får väldigt lite tid över till bloggen, men PHP-artiklarna är skriva för hand redan plus att jag funderar på att skriva mer om Cisco och etisk hacking.

Ha en fortsatt trevlig vinternatt

- Waschman

22 oktober, 2009

Windows 7: Visa skrivbordet

Hej! Jag kände att det var dags att uppdatera lite på bloggen, därför skriver jag här ett tips till er om Windows 7.

Ikonen i snabbstartfältet för att visa skrivbordet fanns i Windows XP och Windows Vista. Men i Windows 7 är ikonen borttagen. Jag fann en guide på Internet hur man gjorde för att få ikonen tillbaka och likna den i Windows Vista. Det fungerade bra. Men det bästa hade väl varit om den funktionen redan fanns i nya Windows 7.

Jag har upptäckt att det finns tre sätt att visa skrivbordet.

Steg för att visa skrivbordet i Windows 7:
  1. Klicka med musen i den vertikala rutan längst ner till höger


    (Klicka på bilden för att endast visa den) Visa skrivbordet i Windows 7 - Alternativ 1

  2. Man kan även högerklicka på aktivitetslisten längst ner på skärmen och sedan välja "Visa skrivbordet" eller "Show the desktop" i engelska versionen.


    (Klicka på bilden för att endast visa den) Visa skrivbordet i Windows 7 - Alternativ 2

  3. Man kan även använda tangentkombinationen Windows + D. Tack för tipset från BosseWeb

För fler tips om Windows 7 kan ni även läsa en artikel från webbtidningen IDG Windows 7 på 2 minuter [1]

Själv kan jag inte använda alla tips för Windows 7 eftersom jag inte har en sån bra laptop där Aero-temat inte fungerar över huvud taget. Aero-temat är (för de som inte vet) det tema i Windows 7 som aktiverar snyggare färger, genomskinlighet, extra funktioner, musrörelser, m.fl. Jag får nöja mig med Firefox och Notepad++ när jag utvecklar webbsidor och ska surfa på Internet.

Ha en fortsatt trevlig dag!

Källreferens
[1] http://www.idg.se/2.1085/1.261217/snabbkoll-windows-7--pa-2-minuter

13 september, 2009

Ljus höst framför oss

Semestern är över och solen närmar sig horisonten fortare för var dag som kommer och tittar förbi. Mycket har hänt och mycket kommer hända nu till hösten. Det kanske inte kommer märkas så mycket på bloggen men jag har många saker att göra, samt några projekt som måste färdigställas.

Några av uppgifterna är att utbilda studenterna vid Halmstad Högskola inom nätverksdesign och datordrift med Cisco-nätverk. Min egna webbsida skall också utvecklas med mitt egna CMS (Content Management System) plus lite annat.

Så hösten tror jag blir väldigt lärorik och medan höstmörkret närmar sig, ser det fortfarande ljust ut på IT fronten. Det kommer fortfarande komma nya artiklar om t.ex PHP, Cisco och Windows 7 och annat smått och gott.

Så jag hoppas ni får trevlig läsning framöver.

MVH
Waschman

Välkomna till bloggen

Välkomna ska ni vara kära besökare. Jag skriver om IT för att det är kul och för att jag vill dela med mig av information och kunskap. Jag försöker hålla bloggen så kategoriserad som möjligt för att ni enklare ska hitta intressanta länkar och artiklar.