can TCP packets arrive to receiver by pieces?
Sim. O IP suporta fragmentação, embora o TCP geralmente tente determinar o caminho do MTU e manter seus pacotes menores do que isso por motivos de desempenho. A fragmentação aumenta a taxa de perda de datagramas catastroficamente. Se um caminho tiver uma taxa de perda de pacotes de 10%, fragmentar um datagrama em dois pacotes faz com que a taxa de perda do datagrama seja de quase 20%. (Se um dos pacotes for perdido, o datagrama será perdido.)
Você não precisa se preocupar com isso, nem com a camada TCP. A camada IP reagrupa os pacotes em datagramas inteiros.
E.g.: if I send 20 bytes using TCP protocol, can I be 100% sure that I will receive exactly 20 bytes at once, not 10 bytes then another 10 bytes or so?
Não, mas isso não tem nada a ver com pacotes. O TCP é, fundamentalmente, um protocolo de fluxo de bytes que não preserva os limites das mensagens do aplicativo.
And the same question for UDP protocol. I know that UDP is unreliable and packets can not arrive at all or arrive in different order,
O mesmo é verdadeiro para o TCP. Pacotes são pacotes. A diferença é que o TCP tem novas tentativas e reordenação incorporadas ao protocolo, enquanto o UDP não faz isso.
but what about 1 packet? If it arrives, can I be sure that it is a complete packet, not a piece?
Não, mas isso não é problema seu. O protocolo UDP lida com a remontagem de datagramas. Isso faz parte do seu trabalho. (Na verdade, o protocolo IP faz isso para o protocolo UDP, então o UDP faz isso simplesmente sendo colocado em camadas em cima do IP.) Se um datagrama é dividido em dois pacotes, o protocolo IP irá remontá-lo para o protocolo UDP. verá os dados completos.