No method "write" when using TCPListener


#1

So I’ve been building a game using Ruby and i’ve used Rust for the server, wanted something with speed. Now i’ve worked with rust before alittle but for some reason i cannot figure this out for the life of me. I have my server set to listen for game updates, update its HashMap then return the updated data to all clients. Simple right? Seems not…

Heres the full code, i know its messy and you will spit your coffee all oer your screen. Its my second attempt at a rust applicaion. Be kind… please.

        use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};
use std::io::{BufReader,BufWriter};
use std::collections::HashMap;

fn main(){
    println!("Server is starting...");

    //will store all active_user data
    let mut active_user_data = HashMap::new();

    println!("Building TCP server...");
    let tcp_listener = TcpListener::bind( "192.168.1.139:6767" ).unwrap();

    for stream in tcp_listener.incoming(){

        let mut stream = stream.unwrap();

                //sort the data from the TCPStream
                let mut reader = BufReader::new(&stream);
                let mut message_string = String::new();
                reader.read_to_string(&mut message_string).expect("Error reading data...");

                //sort the incomming data then return the updated info.
                println!("Game Data Recieved...");
                println!(":)");

                //split the data into a vector so we can add them to the HashMap
                let recieved_data_split = message_string.split("=");

                let recieved_data = recieved_data_split.collect::<Vec<&str>>();

                //need to create varification to check if the username e.g. HashMap key is in use. If so then the
                //new user will have to choose another. Failed update code will be returned and client will prompt
                //for a new username...
                println!("{}", message_string);

                //insert/update the infrmation
                active_user_data.insert(recieved_data[0].to_owned(), recieved_data[1].to_owned());


                //will construct real return data string here, for now i got a sample in the "write" method below...



                //send the data back to the game client...
                println!("Building socket to return data...");

                //error returning the data...
                //no idea what to do here...
                stream.write("cosmo=128:128:d,hazza:343:236:l".as_bytes()).unwrap();

                println!("Returning modified data...");



            }

}

Error is:

error[E0599]: no method named `write` found for type `std::result::Result<std::net::TcpStream, std::io::Error>` in the current scope
  --> lib.rs:52:24
   |
52 |                 stream.write("cosmo=128:128:d,hazza:343:236:l".as_bytes()).unwrap();
   |                        ^^^^^

error: aborting due to previous error

#2

stream is a Result<TcpStream, io::Error> because tcp_listener.incoming() returns an iterator that returns the stream wrapped in a Result. So, if you don’t care about the possibility of the Result being in error, you can just unwrap it to get at the TcpStream:

stream.unwrap().write(...

#3

Hello, thank you for the response. I’ll sort error handling later on for now i’d just like some code that compiles. I’ve made the change you suggested but it now just throws up more errors to do with reading the incoming data. If you want to take a crack at those, or just point me in the right direction then i’ll have another go at it.

i added the "unwrap further up as stream was used by “Buffreader” but that error is sorted. Now the issue comes as it says:

error[E0502]: cannot borrow `stream` as mutable because it is also borrowed as immutable
  --> lib.rs:51:17
   |
20 |                 let mut reader = BufReader::new(&stream);
   |                                                  ------ immutable borrow occurs here
...
51 |                 stream.write("cosmo=128:128:d,hazza:343:236:l".as_bytes()).unwrap();
   |                 ^^^^^^ mutable borrow occurs here
...
57 |             }
   |             - immutable borrow ends here

#4

There are a few ways to solve this, but here’s a straightforward one (i.e. eliminate the reader local):

let mut message_string = String::new();
BufReader::new(&stream).read_to_string(&mut message_string).expect("Error reading data...");

I’m skipping the explanations and deliberately keeping this pretty minimal so you can get the code to compile (I kinda figured you just want to get that going first). If you want some help understanding what’s going on, ask away.