Sending u32 and string content through TCPStream

Hello:
I have a String to send by TCP.
but the telegram need to add how many bytes of the String at the beginning.and the length should be u32.
the struct is like

          let s = String::new("Hello,world");
          length = &s.as_bytes().len() as u32 + 4;

      now I would like to send the length+s as &vec[u8] 
      wtr :v[u8]  = length as vec[u8].extend[ &s.as_bytes() as vec[u8]]
      stream.write(&wtr).unwrap();
      I tried to use crate byteorder  write_u32.  yes I successed.
      but I still wonder how can I do if not use the crate?and write it in a easy way?

String.len() and String.as_bytes().len() are always the same. Rust only counts lengths and offsets in bytes, not "characters".

You never want to use &Vec<u8> for anything. Use &[u8] instead. That's because the key difference between Vec<u8> and [u8] is that Vec can grow, but &Vec is a read-only reference, so it can't grow. It's useless to require a type that can grow, but can't grow.

You seem to be trying to take reference to bytes slice &s.as_bytes(). That's not needed, because as_bytes() returns a reference already (&[u8]).

You can use byteorder crate for this:

use byteorder::{ByteOrder, LittleEndian};
use std::io;

fn write_with_len_prefix(data: impl AsRef<[u8]>, mut writer: impl io::Write)
    -> io::Result<()>
{
    let data = data.as_ref();
    let mut buf = [0u8; 4];
    LittleEndian::write_u32(&mut buf, data.len() as u32);
    writer.write_all(&buf)?;
    writer.write_all(data)?;
    Ok(())
}

send("hello", &mut tcp_stream);

It's a bit more generic than you probably need, but it should demonstrate Rust capabilities.

2 Likes

thanks for your answer.
I have tried byteorder before,it works. but yours looks much clear.
I have found the new function for u32. u32.to_bytes() in nightly version.
https://github.com/rust-lang/rust/issues/49792
so it means I can avoid use the byteorder just for this simple requirement. but when I used it ,the complier provide me the info below:
#![feature(int_to_from_bytes)]
stream.write(&length.to_be().to_bytes());

Running "cargo build":
Compiling rustprj v0.1.0 (file:///D:/projects/rustprj)
error: an inner attribute is not permitted in this context
--> src\main.rs:44:19
|
44 | #![feature(int_to_from_bytes)]
| ^
|
= note: inner attributes, like #![no_std], annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like #[test], annotate the item following them.

error[E0658]: use of unstable library feature 'int_to_from_bytes' (see issue #52963)
--> src\main.rs:45:46
|
45 | stream.write(&length.to_be().to_bytes());
| ^^^^^^^^
|
= help: add #![feature(int_to_from_bytes)] to the crate attributes to enable

error: aborting due to 2 previous errors

how can I slove that? it is the first time for me to use a unstable funtion in a nightly version.

thanks you. It makes me more clear :grinning:

Insert #![feature(int_to_from_bytes)] at the top of your main.rs, before extern crate declarations.