Как я могу отправлять и получать нет как TCP клиент так и сервер VB.NET
Hi everyone. I have been building a vb.net application which works by sharing out data between a TCP clients and TCP server. The data being shared are small XML, CSV and PNG files. I have limited knowledge on TCP projects and thought it be a feasible idea to encode these files to Base64 send them as strings and then once at there destinations un-encode the data from Base64 to the desired file information. This idea just doesn't seem to work and I cant find a solution. Also I find it a bit hard to understand because in previous projects I have sent Base64 encoded strings via TCP regarding data which I wanted to remain confidential such as passwords or email addresses of staff members which works fine. The first thing that I discovered upon Googeling is that the files which though small exceed 50kb would mean that they are better sent of as packets fine I have seen a few easy to follow projects that send files via TCP using packets.... However the projects all seem to be examples of Clients sending to Servers and not visa-versa or as what I want both ways. Determined not to give up I came up with the following code but then ran into problems with it which leads me to believe that bytes sent as packets can only be done in a Server to Client situation? SERVER CODE:
Imports System.Net Imports System.Net.Sockets Imports System.Text Public Class Form1 Dim SERVER As TcpListener Dim LIST_OF_CLIENTS As New List(Of TcpClient) Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Try '(Sets up connection parameters) Dim IP As String = "10.32.48.92" Dim PORT As Integer = 5432 '(Creates an active listner) SERVER = New TcpListener(IPAddress.Parse(IP), PORT) SERVER.Start() '(New thread to keep reciving messages from clients) Threading.ThreadPool.QueueUserWorkItem(AddressOf NEW_CLIENT) Catch ex As Exception MsgBox(ex.Message) End Try End Sub Private Sub NEW_CLIENT() Dim CLIENT As TcpClient = SERVER.AcceptTcpClient Try '(Adds potential new clients) LIST_OF_CLIENTS.Add(CLIENT) '(New thread to keep reciving messages from potential new clients) Threading.ThreadPool.QueueUserWorkItem(AddressOf NEW_CLIENT) While True '(his while puts it on a loop to keep getting messages from client) '(The following gets all incomming messages) Dim NETWORK_STREAM As NetworkStream = CLIENT.GetStream Dim BUFFER_TO_RECIVE(100000) As Byte NETWORK_STREAM.Read(BUFFER_TO_RECIVE, 0, BUFFER_TO_RECIVE.Length) Dim TEXT As String = Encoding.UTF8.GetString(BUFFER_TO_RECIVE) '(The following forward the message to all clients except the client that sent the message) For Each c As TcpClient In LIST_OF_CLIENTS If c IsNot CLIENT Then Dim NEW_NETWORK_STREAM As NetworkStream = c.GetStream() NEW_NETWORK_STREAM.Write(Encoding.UTF8.GetBytes(TEXT), 0, TEXT.Length) End If Next End While Catch ex As Exception '(If connection with client failed we want to remove tht client from list) If LIST_OF_CLIENTS.Contains(CLIENT) Then LIST_OF_CLIENTS.Remove(CLIENT) End If ' MsgBox(ex.Message) ' (by commenting this the error that a client has bombed out dose not apear on screen) End Try End Sub Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load End Sub End Class
КЛИЕНТСКИЙ КОД:
<pre lang="vb"> Imports System.Net Imports System.Net.Sockets Imports System.Text Imports System.IO Public Class Form1 Const BUFFER_SIZE As Integer = 1024 * 20 Dim IP As String = "10.32.48.92" Dim PORT As Integer = 5432 Dim CLIENT As New TcpClient(IP, PORT) Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load '(This connects to server) Try CheckForIllegalCrossThreadCalls = False '(this halts crossthreading errors cased by the way threads work, whic is apparently a big pain in the arse) '(Create a new thread to listen if connection is successfull... for the reciving of any new messages) Threading.ThreadPool.QueueUserWorkItem(AddressOf RECIVE_MESAGES) Me.AcceptButton = Button2 '(This casses the enter key to triggre the button2.click event) Catch ex As Exception MsgBox(ex.Message) End Try End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Try 'sends filename, filelength, filebytes Dim fullfilename As String = "C:\ToSomeFile.png" Dim info As New FileInfo(fullfilename) CLIENT.Connect(Net.IPAddress.Parse(IP), PORT) 'send the file to client IP address 'writes a String and a Long with binarywriter (wrapping networkstream) Dim bw As New BinaryWriter(CLIENT.GetStream) bw.Write(info.Name) bw.Write(info.Length) 'using filestream to read file, writes this directly to networkstream Using fs As New FileStream(fullfilename, FileMode.Open, FileAccess.Read) Dim buffer(BUFFER_SIZE) As Byte Dim reads As Integer = -1 Dim totalRead As Integer = 0 Do Until reads = 0 reads = fs.Read(buffer, 0, buffer.Length) CLIENT.GetStream.Write(buffer, 0, reads) totalRead += reads Loop End Using bw.Close() CLIENT.Close() Catch ex As Exception MsgBox(ex.Message) End Try End Sub Private Sub RECIVE_MESAGES(ByVal ar As IAsyncResult) Try While True Dim buffer(BUFFER_SIZE) As Byte Dim readstotal As Long = 0 'using binaryreader (wrapped networkstream) to read a String and a Long Dim br As New BinaryReader(CLIENT.GetStream) Dim filename, filepath As String, filelen As Long filename = br.ReadString filelen = br.ReadInt64 If filename.ToUpper.Contains("PNG") Then Dim di As New DirectoryInfo(Application.StartupPath & "\PNG") If Not di.Exists Then Directory.CreateDirectory(Application.StartupPath & "\PNG") End If filepath = Path.Combine(Application.StartupPath & "\PNG\", filename) ElseIf filename.ToUpper.Contains("XML") Then Dim di As New DirectoryInfo(Application.StartupPath & "XML") If Not di.Exists Then Directory.CreateDirectory(Application.StartupPath & "\XML") End If filepath = Path.Combine(Application.StartupPath & "\XML\", filename) End If Dim reads As Integer = -1 'using filestream to write read filebytes directly from networkstream Using fs As New FileStream(filepath, FileMode.Create, FileAccess.Write) Do Until readstotal = filelen reads = CLIENT.GetStream.Read(buffer, 0, buffer.Length) fs.Write(buffer, 0, reads) readstotal += reads Loop End Using End While Catch ex As Exception MsgBox(ex.Message) End Try End Sub End Class
I as second attempt then returned to my initial idea and encoded the files to Base64 though this time before sending it via TCP I red the data out to a text-box copying the text-box results and checking on-line with diverse Base64 to Image sites if the Base64 code from the text-box delivered the same image which it did. I then proceeded with sending the data via TCP but am now met with a situation that says the Base64 is incorrect the error says “The input is not a valid base-64 string as it contains a non-base 64 character...” which after some more Googeling has lead me to believe the encoding of the string sent by the TCP corrupted the Base64 format apparently changing it to encoding.UTF8 would fix it however to no avail. The following code show this attempt. SERVER CODE:
Imports System.Net Imports System.Net.Sockets Imports System.Text Public Class Form1 Dim SERVER As TcpListener Dim LIST_OF_CLIENTS As New List(Of TcpClient) Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Try '(Sets up connection parameters) Dim IP As String = "10.43.71.241" Dim PORT As Integer = 5432 '(Creates an active listner) SERVER = New TcpListener(IPAddress.Parse(IP), PORT) SERVER.Start() '(New thread to keep reciving messages from clients) Threading.ThreadPool.QueueUserWorkItem(AddressOf NEW_CLIENT) Catch ex As Exception MsgBox(ex.Message) End Try End Sub Private Sub NEW_CLIENT() Dim CLIENT As TcpClient = SERVER.AcceptTcpClient Try '(Adds potential new clients) LIST_OF_CLIENTS.Add(CLIENT) '(New thread to keep reciving messages from potential new clients) Threading.ThreadPool.QueueUserWorkItem(AddressOf NEW_CLIENT) While True '(his while puts it on a loop to keep getting messages from client) '(The following gets all incomming messages) Dim NETWORK_STREAM As NetworkStream = CLIENT.GetStream Dim BUFFER_TO_RECIVE(1000000) As Byte NETWORK_STREAM.Read(BUFFER_TO_RECIVE, 0, BUFFER_TO_RECIVE.Length) Dim TEXT As String = Encoding.UTF8.GetString(BUFFER_TO_RECIVE) '(The following forward the message to all clients except the client that sent the message) For Each c As TcpClient In LIST_OF_CLIENTS If c IsNot CLIENT Then Dim NEW_NETWORK_STREAM As NetworkStream = c.GetStream() NEW_NETWORK_STREAM.Write(Encoding.UTF8.GetBytes(TEXT), 0, TEXT.Length) End If Next End While Catch ex As Exception '(If connection with client failed we want to remove tht client from list) If LIST_OF_CLIENTS.Contains(CLIENT) Then LIST_OF_CLIENTS.Remove(CLIENT) End If ' MsgBox(ex.Message) ' (by commenting this the error that a client has bombed out dose not apear on screen) End Try End Sub
КЛИЕНТСКИЙ КОД:
<pre lang="vb"> Imports System.Net Imports System.Net.Sockets Imports System.Text Imports System.IO Public Class Form1 Dim CLIENT As TcpClient Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load '(This connects to server) Try Dim IP As String = "10.43.71.241" Dim PORT As Integer = 5432 CLIENT = New TcpClient(IP, PORT) CheckForIllegalCrossThreadCalls = False '(this halts crossthreading errors cased by the way threads work, whic is apparently a big pain in the arse) '(Create a new thread to listen if connection is successfull... for the reciving of any new messages) Threading.ThreadPool.QueueUserWorkItem(AddressOf RECIVE_MESAGES) Me.AcceptButton = Button2 '(This casses the enter key to triggre the button2.click event) Catch ex As Exception MsgBox(ex.Message) End Try End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Dim image As Image = image.FromFile("C:\TOM\jane.png") Dim format As System.Drawing.Imaging.ImageFormat = System.Drawing.Imaging.ImageFormat.Png Using ms As New MemoryStream() ' Convert Image to byte[] image.Save(ms, format) Dim imageBytes As Byte() = ms.ToArray() ' Convert byte[] to Base64 String Dim base64String As String = Convert.ToBase64String(imageBytes) Try Dim NETWORK_STREAM As NetworkStream = CLIENT.GetStream '(Creates the nesesary stream) NETWORK_STREAM.Write(Encoding.UTF8.GetBytes(base64String), 0, base64String.Length) '(Writes the the stream just created in the above step) Catch ex As Exception MsgBox(ex.Message) End Try End Using End Sub Private Sub RECIVE_MESAGES() Try While True Dim NETWORK_STREAM As NetworkStream = CLIENT.GetStream Dim BUFFER_TO_RECIVE(100000) As Byte NETWORK_STREAM.Read(BUFFER_TO_RECIVE, 0, BUFFER_TO_RECIVE.Length) Dim TEXT As String = Encoding.UTF8.GetString(BUFFER_TO_RECIVE) '+++ Dim base64String As String = TEXT ' Convert Base64 String to byte[] Dim imageBytes As Byte() = Convert.FromBase64String(base64String) Dim ms As New MemoryStream(imageBytes, 0, imageBytes.Length) ' Convert byte[] to Image ms.Write(imageBytes, 0, imageBytes.Length) Dim image__1 As Image = Image.FromStream(ms, True) PictureBox1.Image = image__1 Dim bm As New Bitmap(PictureBox1.Image) bm.Save("c:\users\user\desktop\test.png", System.Drawing.Imaging.ImageFormat.Png) '(the following displays the text in ritch textbox) TextBox3.Text = TEXT End While Catch ex As Exception MsgBox(ex.Message) End Try End Sub
I seriously have made effort to try and figure this one out but just cant find the answer can anyone help me?
Что я уже пробовал:
См. выше раздел для примеров, которые я пробовал
Richard MacCutchan
Клиент может отправить что угодно на сервер, а сервер может отправить что угодно клиенту. TCP-это всего лишь протокол для передачи данных между двумя конечными точками, он не заботится о том, что эти данные содержат, и не заботится (или не знает), кто является клиентом, а кто-сервером. Ключ к вашей проблеме-создать протокол обмена сообщениями между вашим клиентом и сервером, чтобы они могли решить, должны ли они быть в режиме отправки или получения в любой момент времени.