If I make a C program (a server and a client) and I run the server on one PC and the client on another host on the same network and start communicating (suppose I know the IP of both of them), how exactly will the NIC of the first computer will know the NIC of the computer with the destination IP?
Vamos assumir o IPv4. Para o IPv6, os princípios são semelhantes, mas os detalhes são diferentes (descoberta do vizinho em vez de ARP).
Primeiro, seu computador procura o endereço IP de destino em sua tabela de roteamento IP. Isto dirá a "interface" e o "endereço IP do próximo salto". Se o destino estiver em uma sub-rede local, o endereço IP do próximo salto será o mesmo que o endereço IP de destino (se o destino não estiver em uma sub-rede local, o endereço IP do próximo salto será o endereço de um gateway).
Em seguida, o computador procura o endereço IP do próximo salto na tabela ARP da interface. Se encontrar uma correspondência com um endereço MAC de destino válido, o pacote poderá ser enviado imediatamente. Caso contrário, o pacote será enfileirado até que um endereço MAC esteja disponível.
Para descobrir o endereço MAC, seu computador envia uma solicitação ARP. A solicitação ARP é enviada para o endereço MAC de transmissão. Se tudo estiver funcionando, o computador do próximo salto (destino no seu caso) responderá à solicitação ARP, o seu computador criará uma entrada em sua tabela arp e os pacotes enfileirados serão enviados.
Se não houver resposta à solicitação ARP, seu sistema provavelmente tentará um número finito de vezes antes de desistir de enviar os pacotes. Dependendo do sistema operacional, ele pode ou não gerar pacotes inacessíveis para o host de destino do ICMP quando ele desiste (o linux, aparentemente, o BSD não tem certeza sobre o Windows).
I know more about how routing works. Basically (? if the computer does not have the ip address in the ARP cache and no host on the network responds to the arp request package) than the host that wants to send the data to some IP will forward the packet to the default gateway (which should be a router) and that router will than check the routing table to see on what port it is connected the NETWORK in which the destination IP is part of. If the network is not in that table then router forwards to its own default route and so on until some router knows the network. Is this correct?
Isso está errado, o gateway padrão é usado quando não há outra entrada na tabela de roteamento IP que corresponda ao IP de destino. Não é usado se o ARP falhar. Usar o gateway padrão se o ARP falhar seria muito provável de criar loops de roteamento.