I'll try to answer your question directly without going into a huge rant about TCP v UDP.
Basically you need to understand that both HTTP and DNS are completely independent applications/protocols. Sometimes you need to actually send a DNS query to a DNS server, sometimes you don't (if the DNS record is cached locally on your PC/Server).
We do NOT have a DNS record cached.
- http://google.com is entered in the browser.
- Your PC checks the local DNS cache, and sees it does NOT have a record for google.com
- A UDP DNS query is sent to a DNS server, in this case it's most likely your ISP's DNS server.
- The DNS server sends a UDP response back.
- You now have your answer in the form of an IP address, now you can initiate your TCP connection to google.com
- The 3-way handshake occurs between you and google.com (SYN, SYN/ACK, ACK) - if you do not know what this is you can search for "TCP 3 way handshake" and find some good information.
- After the handshake completes, HTTP will render in the form of your favorite search engine.
We HAVE a DNS record cached. There is a very small difference here, but I'm going to include the whole thing so you can see the comparison.
- http://google.com is entered in the browser.
- Your PC checks the local DNS cache, and sees it has a record cached in the form of an IP address.
- You now have your IP address for google.com, now you can initiate your TCP connection to google.com
- The 3-way handshake occurs between you and google.com (SYN, SYN/ACK, ACK)
- After the handshake completes, HTTP will render in the form of your favorite search engine.
So just because you're trying to get to a webpage you do not have to send a UDP DNS query. DNS is independent, visiting a webpage is not the only time you'd need to use DNS. Feel free to comment if you need clarification.
In addition to the data some metadata must be communicated betwen the application, transport and internet layers.
Technically how metadata is communicated between layers is an implementation detail. In practice the application layer nearly always uses some variant of the berkerly sockets API to talk to the transport layer.
For TCP clients the destination IP and port are specified to the transport layer as part of the "connect" API call. For UDP clients either "connect" can be used to create a psuedo-connnection or the destination IP and port can be specified on a per-packet basis with the "sendto" api call.
For TCP servers the application can read the IP and port by using by calling getpeername after accepting a connection. UDP servers can read the IP and port for each packet by reading packets using the recvfrom API call.
Unfortunately sendto and recvfrom have a design flaw. They only pass the remote address, not the local one which can cause problems for servers on multihomed hosts. The server may send replies from the wrong IP address causing them to be dropped, either by the network or the client. There are newer APIs to deal with this but the details vary between operating systems.
The transport layer will in turn inform the internet layer of the IP addresses for outgoing packets and the internet layer will inform the transport layer of the IP addresses for incoming packets. Since both the transport and internet layers are typically part of the TCP/IP stack the details of how this is done is an implementation detail inside the stack.
x-forwarded-for is a http header used by http proxies. The proxy will retrieve the client IP address using getpeername, it will then encode it into a http header to pass it on to the next server.
Best Answer
TCP, itself, will send a RST.
This is explained in RFC 793, Transmission Control Protocol:
By the way, TCP does not know anything about clients or servers. TCP creates connections between peers. The client/server concept is for applications, which are off-topic here.