The general concept is...
Browser/Client ---\ /---Kernel
Browser/Client ----*Jupyter*----Kernel
Browser/Client ---/ \---Kernel
where "Jupyter" can be a notebook server or kernel gateway. As Thomas explained, the kernels execute code. The browser or other client decides what should be executed, and gets the results.
If you have a Jupyter Notebook server, Jupyter knows about notebooks. Jupyter loads and saves notebooks as instructed by the client, and starts and stops kernels. When a cell is executed, just the code of that cell is sent by the client to the kernel that was started for the notebook. Jupyter serves as a kind of router or bridge that translates websocket connections from the client into ZeroMQ connections to the kernel.
If you have a Jupyter Kernel Gateway server in websocket mode, there are neither notebooks nor code cells. Clients provide code snippets directly. Jupyter still starts and stops kernels, and translates websocket connections into ZeroMQ connections.
hope that helps,
Roland