CodeBlanks Logo Icon CodeBlanks

TCP listener

Accept clients in a loop with TcpListener.

Chat server: TCP listener

In this project we'll build a chat server where several clients connect and exchange messages. The first step is accepting connections: TcpListener::bind listens on an address, accept waits until a client connects and returns a TcpStream:

use std::net::TcpListener;

let dinleyici = TcpListener::bind("127.0.0.1:7878")?;
for baglanti in dinleyici.incoming() {
    let akis = baglanti?;
    println!("bağlandı: {}", akis.peer_addr()?);
}

If port 0 is given, the operating system picks a free port; you learn which with local_addr(). It's handy for tests.

Reading and writing

TcpStream implements both Read and Write. In a line-based protocol, BufReader::read_line is used for reading and writeln! for writing:

use std::io::{BufRead, BufReader, Write};
use std::net::TcpStream;

let mut istemci = TcpStream::connect(adres)?;
writeln!(istemci, "merhaba")?;

let (akis, _) = dinleyici.accept()?;
let mut satir = String::new();
BufReader::new(akis).read_line(&mut satir)?;

Practice First connection

Listen on 127.0.0.1:0 and get the address with local_addr(). Let a thread connect to that address and write the line merhaba. Let the main thread take the connection with accept, read the line and print alındı: merhaba.

Starter code

main.rs
use std::io::{self, BufRead, BufReader, Write};
use std::net::{TcpListener, TcpStream};
use std::thread;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::io::{self, BufRead, BufReader, Write};
use std::net::{TcpListener, TcpStream};
use std::thread;

fn main() -> io::Result<()> {
    let dinleyici = TcpListener::bind("127.0.0.1:0")?;
    let adres = dinleyici.local_addr()?;
    let istemci = thread::spawn(move || -> io::Result<()> {
        let mut akis = TcpStream::connect(adres)?;
        writeln!(akis, "merhaba")?;
        Ok(())
    });
    let (akis, _) = dinleyici.accept()?;
    let mut s = String::new();
    BufReader::new(akis).read_line(&mut s)?;
    println!("alındı: {}", s.trim());
    istemci.join().unwrap()?;
    Ok(())
}

Expected output

alındı: merhaba

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 When does the <code>incoming()</code> loop end?

  • Never; the server keeps waiting for new connections Correct answer
  • After the first connection
  • When there are no connections left
  • After a second

Explanation: .take(n) can be used for a fixed number of connections; in tests this makes the loop end.

2 Accept a connection

Question
let (akis, adres) = dinleyici.____()?;
Answer
let (akis, adres) = dinleyici.accept()?;

Explanation: accept waits until a client connects.

3 Function and role

Term Meaning
TcpListener::bind Listens on an address
accept() Waits for a connection
TcpStream::connect Connects to a server
local_addr() Actual port

All lessons in Advanced