Register Register Member Login Member Login Member Login Forgot Password ??
PHP , ASP , ASP.NET, VB.NET, C#, Java , jQuery , Android , iOS , Windows Phone
 

Registered : 109,036

HOME > .NET Framework > Forum > TcpListener multiple send file ดีบั๊กสเต็ปทำงานได้แต่พอรันจริงไม่ได้



 

TcpListener multiple send file ดีบั๊กสเต็ปทำงานได้แต่พอรันจริงไม่ได้

 



Topic : 094151



โพสกระทู้ ( 52 )
บทความ ( 0 )



สถานะออฟไลน์




ผมเอาตัวอย่างจากเว็บนี้มาใช้ครับ
http://www.vbforums.com/showthread.php?390875-Client-Server-Socket-classes-for-file-transfer

UI Program จะเป็นฝั่ง Server listening รอรับการเชื่อมต่อจาก Client โดยไคลเอนต์ใส่ IP Server ผมทดลองโดยใส่ IP เครื่องตัวเอง

1

ตัวอย่างที่ผมโหลดมามันจะเป็นลักษณะ Client send string request ชื่อไฟล์ไฟล์ไปที่ Server
Server ก็จะนำชื่อไฟล์ที่ได้รับเข้ามาไปอ่านไฟล์ที่ C:\bin\
{Message string file name} เป็น FileStream ส่งกลับไปที่ Client
แล้วไคลเอนต์ก็จะเขียนไฟล์เก็บไว้ที่ C:\

แต่สิ่งที่ผมต้องการคือ เซิร์ฟเวอร์ส่งไฟล์ที่กำหนดไว้(เป็นชุดหลายไฟล์)ไปให้ไคลเอนต์(โปรแกรมร้านสาขา)เก็บไฟล์ไว้

ซึ่งตอนนี้โปรแกรมผม เซิร์ฟเวอร์ส่งทีละไฟล์ได้ ไคลเอนต์รับแล้วเขียนไฟล์เก็บได้ พอดีบั๊กรันสเต็ปก็ส่งแบบวนลูปไปเรื่อยๆ 10 ไฟล์ ก็บันทึกได้ครบปกติดี
แต่พอรันจริงกลับส่งแล้วเขียนได้ไม่ครบจำนวน(และไม่แฮงค์) แต่ไฟล์โปรแกรม frmServer ก็จะ Not Responding ค้างไปเลย
โดยตอนจะแฮงค์ฝั่งไคลเอนต์หน้าจอ Output ของ vs ที่ผมสั่งให้ debug.print( message file name ) ที่รับเข้ามาไว้ มันจะเห็นมีอักขระพิเศษ พ่วงท้ายมากับเมสเสจชื่อไฟล์ ซึ่งดีบั๊กดูแล้วไม่มีในตอนฝั่งส่ง มามีเอาตอนฝั่งรับครับ
ตอนนี้ยังติดอยู่ปัญหานี้ปัญหาเดียวเลยครับคือ วนลูปส่งไฟล์ต่อเนื่องไม่ได้ message จะติดอักขระแปลกๆพ่วงท้ายมา แก้ไม่ถูกจริงๆครับ

รูปที่รันแล้วมี Error สังเกตุที่ Output ของ vs

2

ถ้าเป็นอย่างนี้เมื่อไหร่ ฝั่งเซิร์ฟเวอร์จะ Not Responding ค้างไปเลย แต่ไคลเอนต์ไม่เป็นไร แต่จะหยุดเขียนไฟล์ บันทึกได้แค่ไฟล์ก่อนหน้านั้น
ลองวนลูป Send ส่ง message อย่างเดียวทำงานได้ แต่ถ้า SendFile ด้วยพอวนลูปแล้วจะค้าง
ยกเว้นว่าพอส่งไฟล์เสร็จใส่ System.Threading.Thread.Sleep นานๆหน่อยซัก 6 วิก็จะส่งได้ปกติ แต่ไม่รู้ว่าถ้าใช้จริงเจอเน็ตเต่าจะเป็นยังไง
ไม่รู้ว่าเป็นเพราะอะไรรบกวนผู้รู้ช่วยชี้แนะวิธีการ(ให้คนไม่ค่อยเป็น)ด้วยครับ

ต้องขอออกตัวว่าผมปกติจะจับแต่ php ส่วน WinApp vb.net แค่พอเขียนได้ระดับนึง
ส่วน Concept การ Send file แบบ TCP ตัวนี้ผมไม่เข้าใจเลยว่ามีคอนเซ็ป มีลำดับจริงๆเป็นยังไง อ่านหลายวันแล้วแต่ติดด้านภาษาเลยไม่ค่อยเข้าใจ อยากให้ช่วยอธิบายหน่อยครับ
เพราะโปรแกรมนี้ตอนแรกมันเป็น Download file จากปลายทาง (Client Send ไปเพื่อดาวโหลดจาก Server)
ตอนนี้ ผมลองจนสามารถส่งข้อมูลไปกลับแบบ 2ทางได้แล้ว


โปรแกรม 2 ฝั่งจะมีแค่ 4 ไฟล์นะครับ คือ
Server 3 ไฟล์ : tcpConnection.vb, clsListener.vb, frmServer.vb
Client 2 ไฟล์ : tcpConnection.vb, frmClient
[color=blue]ถ้าเมตตาจะทดลอง Debug สามารถ Download File ที่นี่ครับ

http://www.boyr.com/getfile.php?id=1369860&key=51774a7f9cdd2
ต้องคลายซิปไว้ที่ไดรว์ C: จะได้โฟลเดอร์ bin ขึ้นมานะครับ เมื่อรันโปรแกรมและมีการส่งรูปมาเขียนไฟล์สำเร็จ ไฟล์จะถูกเขียนไว้ที่ C: ครับ



Tag : .NET, Win (Windows App), VB.NET, VS 2005 (.NET 2.x), Windows









ประวัติการแก้ไข
2013-04-23 22:37:09
2013-04-23 22:38:42
2013-04-23 22:44:50
2013-04-23 22:45:19
2013-04-24 09:58:49
2013-04-24 10:05:00
2013-04-24 10:08:52
2013-04-24 10:14:15
2013-04-24 10:16:44
2013-04-24 11:58:58
2013-04-25 00:02:12
2013-04-25 10:42:39
2013-04-25 22:19:19
Move To Hilight (Stock) 
Send To Friend.Bookmark.
Date : 2013-04-23 22:34:34 By : Giguntic View : 3078 Reply : 6
 

 

No. 1



โพสกระทู้ ( 52 )
บทความ ( 0 )



สถานะออฟไลน์


โค๊ดเดียวกันทั้งฝั่ง Server และ Client
Code (VB.NET) tcpConnection.vb
Option Strict On
Option Explicit On

Imports System.Net.Sockets
Imports System.IO

Public Class tcpConnection
    Private Enum RequestTags As Byte
        Connect = 1
        Disconnect = 2
        DataTransfer = 3
        StringTransfer = 4
        ByteTransfer = 5
    End Enum

    Private PACKET_SIZE As Int16 = 4096
    Private client As TcpClient
    Private readByte(0) As Byte
    Private myTag As Byte
    Private isConnected As Boolean 'set to true when connection is granted by server

#Region "Declare events"
    Public Event DataReceived(ByVal sender As tcpConnection, ByVal msgTag As Byte, ByVal mstream As MemoryStream)
    Public Event MessageReceived(ByVal sender As tcpConnection, ByVal msgTag As Byte)
    Public Event StringReceived(ByVal Sender As tcpConnection, ByVal msgTag As Byte, ByVal message As String)
    Public Event SetProgress(ByVal IntPercent As Integer)
    Public Event TransferProgress(ByVal Sender As tcpConnection, ByVal msgTag As Byte, ByVal Percentage As Single)
    Public Event Connect(ByVal sender As tcpConnection)
    Public Event Disconnect(ByVal sender As tcpConnection)
#End Region

#Region "Overloaded Constructors and destructor"
    Public Sub New(ByVal client As TcpClient, ByVal PacketSize As Int16)
        'instantiates class for use in server
        'don't handle errors here, allow caller to handle them
        PACKET_SIZE = PacketSize
        Me.client = client
        'Start an asynchronous read from the NetworkStream
        Me.client.GetStream.BeginRead(readByte, 0, 1, AddressOf ReceiveOneByte, Nothing)
    End Sub

    Public Sub New(ByVal IPServer As String, ByVal Port As Integer)
        'instantiates class for use in client
        'don't handle errors here, allow caller to handle them
        'create a new TcpClient and make a synchronous connection
        'attempt to the provided host name and port number
        Me.client = New TcpClient(IPServer, Port)
        'Start an asynchronous read from the NetworkStream
        Me.client.GetStream.BeginRead(readByte, 0, 1, AddressOf ReceiveOneByte, Nothing)
    End Sub

    Protected Overrides Sub finalize()
        'we don't care about errors in this section since we are ending
        On Error Resume Next
        If isConnected Then Send(RequestTags.Disconnect)
        client.GetStream.Close()
        client.Close()
        client = Nothing
    End Sub

#End Region

    Public Property Tag() As Byte
        Get
            Tag = myTag
        End Get
        Set(ByVal value As Byte)
            myTag = value
        End Set
    End Property

    Private Sub ReceiveOneByte(ByVal ar As IAsyncResult)
        'This is where the data is received.  All data communications
        'begin with a one-byte identifier that tells the class how to
        'handle what is to follow.
        Dim r As BinaryReader
        Dim sreader As StreamReader
        Dim mStream As MemoryStream
        Dim lData As Int32
        Dim readBuffer(PACKET_SIZE) As Byte
        Dim StrBuffer(PACKET_SIZE) As Char
        Dim passThroughByte As Byte
        Dim nData As Integer
        Dim lenData As Integer

        SyncLock client.GetStream
            'if error occurs here then socket has closed
            Try
                client.GetStream.EndRead(ar)
            Catch
                RaiseEvent Disconnect(Me)
                Exit Sub
            End Try
        End SyncLock
        'this is the instruction on how to handle the rest of the data to come.
        Select Case readByte(0)
            Case RequestTags.Connect
                'sent from server to client informing client that a successful
                'connection negotiation has been made and the connection now exists.
                isConnected = True 'identifies this class as on the client end
                RaiseEvent Connect(Me)
                SyncLock client.GetStream
                    r = New BinaryReader(client.GetStream)
                    PACKET_SIZE = r.ReadInt16
                    'Continue the asynchronous read from the NetworkStream
                    Me.client.GetStream.BeginRead(readByte, 0, 1, AddressOf ReceiveOneByte, Nothing)
                End SyncLock

            Case RequestTags.Disconnect
                'sent to either client or server
                'propagated forward to Listener on server end
                RaiseEvent Disconnect(Me)

            Case RequestTags.DataTransfer
                'a block of data is coming
                'Format of this transaction is
                '   DataTransfer identifier byte
                '   Pass-Through Byte contains user defined data
                '   Length of data block (max size = 2,147,483,647 bytes)
                SyncLock client.GetStream
                    r = New BinaryReader(client.GetStream)
                    'next we expect a pass-through byte
                    client.GetStream.Read(readByte, 0, 1)
                    passThroughByte = readByte(0)
                    'next expect length of data (Int32)
                    nData = r.ReadInt32
                    lenData = nData
                    'now comes the data, save it in a memory stream
                    mStream = New MemoryStream
                    RaiseEvent SetProgress(0)
                    While nData > 0
                        RaiseEvent TransferProgress(Me, passThroughByte, CSng(1.0 - nData / lenData))
                        lData = client.GetStream.Read(readBuffer, 0, PACKET_SIZE)
                        mStream.Write(readBuffer, 0, lData)
                        nData -= lData
                    End While
                    RaiseEvent SetProgress(100)
                    'Continue the asynchronous read from the NetworkStream
                    Me.client.GetStream.BeginRead(readByte, 0, 1, AddressOf ReceiveOneByte, Nothing)
                End SyncLock
                'once all data has arrived, pass it on to the end user as a stream
                RaiseEvent DataReceived(Me, passThroughByte, mStream)
                mStream.Dispose()

            Case RequestTags.StringTransfer
                'Here we receive the transfer of string data in a block
                'not to exceed PACKET_SIZE in length.
                SyncLock client.GetStream
                    sreader = New StreamReader(client.GetStream)
                    'next we expect a pass-through byte
                    client.GetStream.Read(readByte, 0, 1)
                    passThroughByte = readByte(0)
                    nData = sreader.Read(StrBuffer, 0, PACKET_SIZE)
                End SyncLock
                Dim strX As New String(StrBuffer, 0, nData)

                'pass string on to end user
                RaiseEvent StringReceived(Me, passThroughByte, strX)
                SyncLock client.GetStream
                    'Continue the asynchronous read from the NetworkStream
                    Me.client.GetStream.BeginRead(readByte, 0, 1, AddressOf ReceiveOneByte, Nothing)
                End SyncLock

            Case RequestTags.ByteTransfer
                'Here we receive a user-defined one-byte message
                SyncLock client.GetStream
                    client.GetStream.Read(readByte, 0, 1)
                End SyncLock
                'pass byte on to end user
                RaiseEvent MessageReceived(Me, readByte(0))
                SyncLock client.GetStream
                    'Continue the asynchronous read from the NetworkStream
                    Me.client.GetStream.BeginRead(readByte, 0, 1, AddressOf ReceiveOneByte, Nothing)
                End SyncLock

        End Select
    End Sub

#Region "Overloaded methods to send data between client(s) and server"

    Public Sub Send(ByVal msgTag As Byte)
        ' This subroutine sends a one-byte response
        SyncLock client.GetStream
            Dim writer As New BinaryWriter(client.GetStream)
            'notify that 1-byte is coming
            writer.Write(RequestTags.ByteTransfer)
            'Send user defined message byte
            writer.Write(msgTag)
            ' Make sure all data is sent now.
            writer.Flush()
        End SyncLock
    End Sub

    Public Sub Send(ByVal msgTag As Byte, ByVal strX As String)
        'sends a string of max length PACKET_SIZE
        SyncLock client.GetStream
            Dim writer As New StreamWriter(client.GetStream)
            'Notify other end that a string block is coming
            writer.Write(Chr(RequestTags.StringTransfer))
            'Send user defined message byte
            writer.Write(Chr(msgTag))
            'Send the string
            writer.Write(strX)
            'make sure all data gets sent now
            writer.Flush()
        End SyncLock
    End Sub

    Public Sub Send(ByVal msgTag As Byte, ByVal byteData() As Byte)
        'sends array of byte data
        SyncLock client.GetStream
            Dim writer As New BinaryWriter(client.GetStream)
            'Notify that byte data is coming
            writer.Write(RequestTags.DataTransfer)
            'send user-define message byte
            writer.Write(msgTag)
            'send length of data block
            writer.Write(byteData.Length)
            'send the data
            writer.Write(byteData)
            'make sure all data is sent
            writer.Flush()
        End SyncLock
    End Sub

    Public Sub SendFile(ByVal msgTag As Byte, ByVal FilePath As String)
        'max filesize is 2GB
        Dim byteArray() As Byte
        Dim fs As FileStream = New FileStream(FilePath, FileMode.Open, FileAccess.Read)
        Dim r As New BinaryReader(fs)

        SyncLock client.GetStream
            Dim w As New BinaryWriter(client.GetStream)
            'notify that file data is coming
            w.Write(RequestTags.DataTransfer)
            'send user-define message byte
            w.Write(msgTag)
            'send size of file
            w.Write(CInt(fs.Length))
            'Send the file data
            Do
                'read data from file
                byteArray = r.ReadBytes(PACKET_SIZE)
                'write data to Network Stream
                w.Write(byteArray)
            Loop While byteArray.Length = PACKET_SIZE
            'make sure all data is sent
            w.Flush()
        End SyncLock
    End Sub
#End Region

End Class









ประวัติการแก้ไข
2013-04-23 22:48:18
แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2013-04-23 22:38:53 By : Giguntic
 


 

No. 2



โพสกระทู้ ( 52 )
บทความ ( 0 )



สถานะออฟไลน์


โปรแกรมฝั่ง Server
Code (VB.NET) clsListener.vb
Option Strict On
Option Explicit On

Imports System.Net.Sockets
Imports System.IO
Imports System.Collections.Generic

Public Class clsListener
    Private Enum RequestTags As Byte
        Connect = 1
        Disconnect = 2
        DataTransfer = 3
        StringTransfer = 4
        ByteTransfer = 5
    End Enum

    Private Server As TcpListener
    Private Clients As Dictionary(Of Int16, tcpConnection)
    Private nClients As Byte
    Private mPacketSize As Int16

#Region "Event Declarations"
    Public Event ConnectionRequest(ByVal Requestor As TcpClient, ByRef AllowConnection As Boolean)
    Public Event DataReceived(ByVal Client As tcpConnection, ByVal msgTag As Byte, ByVal mStream As MemoryStream)
    Public Event MessageReceived(ByVal Client As tcpConnection, ByVal message As Byte)
    Public Event StringReceived(ByVal Client As tcpConnection, ByVal msgTag As Byte, ByVal message As String)
    Public Event Disconnect(ByVal Client As tcpConnection)
#End Region

    Public Sub New(ByVal nPort As Integer, Optional ByVal PacketSize As Int16 = 4096)
        'constructor:
        'Creates a dictionary to store client connections
        'and starts listening for connection requests on the
        'port specified
        mPacketSize = packetsize
        Clients = New Dictionary(Of Int16, tcpConnection)
        Listen(nPort)
    End Sub

    Private Sub Listen(ByVal nPort As Integer)
        'instantiate the listener class
        Server = New TcpListener(System.Net.IPAddress.Any, nPort)
        'start listening for connection requests
        Server.Start()
        'asyncronously wait for connection requests
        Server.BeginAcceptTcpClient(New AsyncCallback(AddressOf DoAcceptTcpClientCallback), Server)
    End Sub

    Private Sub DoAcceptTcpClientCallback(ByVal ar As IAsyncResult)
        ' Processes the client connection request.
        ' A maximum of 255 connections can be made.
        Dim Allowed As Boolean

        ' Get the listener that handles the client request.
        Dim listener As TcpListener = CType(ar.AsyncState, TcpListener)

        Dim client As TcpClient = listener.EndAcceptTcpClient(ar)
        'ask end user if he wants to accept this connection request
        RaiseEvent ConnectionRequest(client, Allowed)

        If Not Allowed Then
            SendMessage(RequestTags.Disconnect, 0, client)
            client.GetStream.Close()
            client.Close()
            client = Nothing
        Else
            'add client to list of connected clients
            SendMessage(RequestTags.Connect, mPacketSize, client)
            Dim newClient As tcpConnection = New tcpConnection(client, mPacketSize)
            newClient.Tag = nClients
            Clients.Add(nClients, newClient)
            nClients += CByte(1)

            'need to delegate events for client since client
            'is created dynamically and is going to be put into a
            'collection so this is how we are going to propagate
            'the events up to the end user
            AddHandler newClient.DataReceived, AddressOf onDataReceived
            AddHandler newClient.MessageReceived, AddressOf onMessageReceived
            AddHandler newClient.StringReceived, AddressOf onStringReceived
            AddHandler newClient.Disconnect, AddressOf onClientDisconnect
            newClient = Nothing
        End If

        'continue listening
        listener.BeginAcceptTcpClient(New AsyncCallback(AddressOf DoAcceptTcpClientCallback), listener)

    End Sub 'DoAcceptTcpClientCallback

    Private Sub SendMessage(ByVal msgTag As Byte, ByVal msg As Int16, ByVal client As TcpClient)
        ' This subroutine sends a one-byte response through a tcpClient
        ' Synclock ensure that no other threads try to use the stream at the same time.
        SyncLock client.GetStream
            Dim writer As New BinaryWriter(client.GetStream)
            writer.Write(msgTag)
            writer.Write(msg)
            ' Make sure all data is sent now.
            writer.Flush()
        End SyncLock
    End Sub

#Region "Overloaded Broadcast methods send data to all client connections"
    Public Sub Broadcast(ByVal msgTag As Byte)
        For Each myClient As KeyValuePair(Of Short, tcpConnection) In Clients
            Clients(myClient.Key).Send(msgTag)
        Next
    End Sub

    Public Sub Broadcast(ByVal msgTag As Byte, ByVal strX As String)
        For Each myClient As KeyValuePair(Of Short, tcpConnection) In Clients
            Clients(myClient.Key).Send(msgTag, strX)
        Next
    End Sub

    Public Sub Broadcast(ByVal msgTag As Byte, ByVal byteData() As Byte)
        For Each myClient As KeyValuePair(Of Short, tcpConnection) In Clients
            Clients(myClient.Key).Send(msgTag, byteData)
        Next
    End Sub
#End Region

#Region "Events handlers for the clients"
    Private Sub onClientDisconnect(ByVal Client As tcpConnection)
        RaiseEvent Disconnect(Client)
        'close client and remove from collection
        Clients.Remove(Client.Tag)
        Client = Nothing
    End Sub

    Private Sub onDataReceived(ByVal client As tcpConnection, ByVal msgTag As Byte, ByVal mstream As MemoryStream)
        RaiseEvent DataReceived(client, msgTag, mstream)
    End Sub

    Private Sub onMessageReceived(ByVal Client As tcpConnection, ByVal message As Byte)
        RaiseEvent MessageReceived(Client, message)
    End Sub

    Private Sub onStringReceived(ByVal Sender As tcpConnection, ByVal msgTag As Byte, ByVal message As String)
        RaiseEvent StringReceived(Sender, msgTag, message)
    End Sub
#End Region

End Class

แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2013-04-23 22:40:10 By : Giguntic
 

 

No. 3



โพสกระทู้ ( 52 )
บทความ ( 0 )



สถานะออฟไลน์


โปรแกรมฝั่ง Server
Code (VB.NET) frmServer.vb
Option Strict On

Imports System.Net.Sockets
Imports System.IO

Public Class frmServer
    Inherits System.Windows.Forms.Form

    'This is the port number we will monitor
    Const PORT_NUM As Integer = 10000
    'This is the number of bytes to transfer in one block
    Const PACKET_SIZE As Short = 8192

    Private WithEvents listener As clsListener
    Private WithEvents serverSend As tcpConnection

    'This is where the files are stored on the server
    Private Const picDir As String = "C:\bin\"
    Private Const fileDir As String = "C:\bin\"
    'File name to send
    Dim FileName As String

    'สร้าง Delagate และส่งชื่อ Sub ที่ต้องการจะชี้ให้ไปทำงาน
    Dim UpdateLable As New UpdateText(AddressOf UpdateTextHandler)

    'These are message tags designed for this particular app
    Enum Requests As Byte
        PictureFile = 1
        DataFile = 2
    End Enum

    Private Sub frmServer_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'start listening on our port as soon as the form loads
        listener = New clsListener(PORT_NUM, PACKET_SIZE)
    End Sub

#Region "Button Click"
    Private Sub cmdSendFile1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSendFile1.Click
        'serverSend.Send(1, "test_get_pic.jpg")
        'lblStatusListener.Text = "การส่ง"
        Dim i2 As Integer
        For i2 = 0 To lbFileNameSend.Items.Count - 1
            FileName = lbFileNameSend.Items.Item(i2).ToString
            listener.Broadcast(2, FileName)                         ' แก้ไขแล้ว
            listener.BroadcastFile(2, fileDir & FileName)      ' อันนี้ต้องไปเพิ่ม Method BroadcastFile ใน clsListener.vb เอา
            lblStatusListener.Text &= vbCrLf & "Send " & FileName & " Success."
            'MsgBox(i2 + 1 & ". " & FileName & " : Click to Next")
            'ถ้า Sleep ไม่นานพอ จะส่งหลายไฟล์ต่อเนื่องไม่ได้และที่ช่อง Output ของ Client จะแสดงอักขระพิเศษต่อท้ายเกินมาจาก message ที่ส่งไป
            System.Threading.Thread.Sleep(1000)
        Next
    End Sub
#End Region

    Private Sub listener_ConnectionRequest(ByVal requestor As TcpClient, _
        ByRef AllowConnection As Boolean) Handles listener.ConnectionRequest
        'Here you can examine the requestor to determine whether to accept the connection or not
        Debug.Print("Connection Request")
        'IP Address Client Requestor
        'MsgBox(requestor.Client.RemoteEndPoint.ToString.Substring(0, requestor.Client.RemoteEndPoint.ToString.IndexOf(":")))
        'ถ้า New serverSend แล้วจะทำให้ server send file ได้ แต่ Client จะกด Button Request file แล้ว Server ไม่ SendFile
        'serverSend = New tcpConnection(requestor, PACKET_SIZE)
        AllowConnection = True

        'ตรวจสอบ object lblStatusListener ว่าขณะนี้ต้อง invork กลับไป MainThread หรือไม่
        If lblStatusListener.InvokeRequired Then
            'ทำการเรียก Sub และส่ง string value
            Me.Invoke(UpdateLable, "ถูกปลายทางเชื่อมต่อแล้ว")
            'ถ้าอยู่ใน MainThread
        Else
            'ทำการ เรียก Sub เพื่อ update ได้เลย
            UpdateTextHandler("ถูกปลายทางเชื่อมต่อแล้ว")
        End If
    End Sub

#Region "Delegate Sub"
    'Delegate เพื่อใช้ในการชี้ตำแหน่งของ Function หรือ Sub
    Public Delegate Sub UpdateText(ByVal recvData As String)
    'Sub สร้างไว้เพื่อใช้ในการ update label หรือ control ที่ต้องการ
    Public Sub UpdateTextHandler(ByVal recvData As String)
        lblStatusListener.Text = recvData
    End Sub
#End Region

#Region "Data Reception Events"
    Private Sub listener_DataReceived(ByVal Sender As tcpConnection, ByVal msgtag As Byte, _
        ByVal mStream As System.IO.MemoryStream) Handles listener.DataReceived
        Debug.Print("Data Received from Client: " & CStr(mStream.Length))
    End Sub

    Private Sub listener_MessageReceived(ByVal sender As tcpConnection, ByVal message As Byte) _
        Handles listener.MessageReceived
        Debug.Print("Message Received from Client: " & CStr(message))
    End Sub

    Private Sub listener_StringReceived(ByVal Sender As tcpConnection, ByVal msgTag As Byte, _
        ByVal message As String) Handles listener.StringReceived
        'This is where the client will send us requests for file data using our
        ' predefined message tags
        Debug.Print("String Received from Client: " & message)
        Select Case msgTag
            Case Requests.PictureFile
                Sender.SendFile(msgTag, picDir & message)
            Case Requests.DataFile
                Sender.SendFile(msgTag, fileDir & message)
        End Select
        'ตรวจสอบ object lblStatusListener ว่าขณะนี้ต้อง invork กลับไป MainThread หรือไม่
        If lblStatusListener.InvokeRequired Then
            'ทำการเรียก Sub และส่ง string value
            Me.Invoke(UpdateLable, "Send File " & message & " เสร็จแล้ว")
            'ถ้าอยู่ใน MainThread
        Else
            'ทำการ เรียก Sub เพื่อ update ได้เลย
            UpdateTextHandler("Send File " & message & " เสร็จแล้ว")
        End If
    End Sub
#End Region

End Class



ประวัติการแก้ไข
2013-04-23 22:59:28
2013-04-24 11:40:20
2013-04-25 22:25:35
2013-04-25 22:26:37
แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2013-04-23 22:41:00 By : Giguntic
 


 

No. 4



โพสกระทู้ ( 52 )
บทความ ( 0 )



สถานะออฟไลน์


โปรแกรมฝั่ง Client
Code (VB.NET) frmClient.vb
Option Strict On
Option Explicit On

'Imports System.Net.Sockets
Imports System.Text
Imports System.IO
Public Class frmClient
    Inherits System.Windows.Forms.Form
    Const PORT_NUM As Integer = 10000
    Const DIRECTORY_SAVE As String = "C:\"
    Const TEST_GET_PIC As String = "test_get.jpg"
    Const GET_FILE_1 As String = "z1.zip"
    Const GET_FILE_2 As String = "z2.zip"
    Dim GetFile As String

    Private WithEvents client As tcpConnection

    Enum Requests As Byte
        PictureFile = 1
        DataFile = 2
    End Enum

    Private Sub frmClient_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        cmdGetPicture.Enabled = False
        cmdGetFile1.Enabled = False
        cmdGetFile2.Enabled = False
        'let's ignore all illegal cross thread calls for now
        CheckForIllegalCrossThreadCalls = False
        cmdGetPicture.Text &= vbCrLf & TEST_GET_PIC
        cmdGetFile1.Text &= vbCrLf & GET_FILE_1
        cmdGetFile2.Text &= vbCrLf & GET_FILE_2
    End Sub

#Region "Buttons"
    Private Sub cmdConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdConnect.Click
        Try
            client = New tcpConnection(txtServer.Text, PORT_NUM)
            AddHandler client.StringReceived, AddressOf onStringReceived
        Catch ex As Exception
            MessageBox.Show(Me, ex.Message, "Network Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Me.Dispose()
        End Try
    End Sub

    Private Sub cmdGetPicture_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles cmdGetPicture.Click
        PictureBox1.Image = Nothing
        'request a picture file from server
        client.Send(Requests.PictureFile, TEST_GET_PIC)
    End Sub

    Private Sub cmdGetFile1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles cmdGetFile1.Click
        GetFile = GET_FILE_1
        'request a file from server
        client.Send(Requests.DataFile, GetFile)
    End Sub

    Private Sub cmdGetFile2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdGetFile2.Click
        GetFile = GET_FILE_2
        client.Send(Requests.DataFile, GetFile)
    End Sub

#End Region 'Buttons

#Region "Client Events"
    Private Sub client_Connect(ByVal sender As tcpConnection) Handles client.Connect
        'This event will be raised in a different thread than the original
        ' thread of this form
        Me.Text = "Connected"
        cmdGetPicture.Enabled = True
        cmdGetFile1.Enabled = True
        cmdGetFile2.Enabled = True
        cmdConnect.Enabled = False
    End Sub

    Private Sub client_Disconnect(ByVal sender As tcpConnection) Handles client.Disconnect
        'This event will be raised in a different thread than the original thread of thid form
        Me.Text = "Disconnected"
        MessageBox.Show(Me, "Server has disconnected us or refused our connection", "Server Message")
        cmdGetPicture.Enabled = False
        cmdGetFile1.Enabled = False
        cmdGetFile2.Enabled = False
        cmdConnect.Enabled = True
    End Sub

    Private Sub client_DataReceived(ByVal Sender As tcpConnection, ByVal msgTag As Byte, _
        ByVal mstream As System.IO.MemoryStream) Handles client.DataReceived
        'This code is run in a seperate thread from the thread that started the form
        'so we must either handle any control access in a special thread-safe way
        'or ignore illegal cross thread calls
        Select Case msgTag
            Case Requests.PictureFile
                'picture data, put into our local picturebox control
                SetPicture(mstream)
            Case Requests.DataFile
                'file data, save to a local file
                'GetFile = Mid(GetFile, 8, Len(GetFile))
                SaveFile(DIRECTORY_SAVE & GetFile, mstream)
        End Select
    End Sub

    Private Sub client_SetProgress(ByVal IntPercent As Integer) Handles client.SetProgress
        SetProgressBar(IntPercent, ProgressBar1)
        If Me.ProgressBar1.InvokeRequired Then
            Dim d As New VisibleControl(AddressOf VisibleProgressBar)
            Me.Invoke(d, ProgressBar1)
        Else
            VisibleProgressBar(ProgressBar1)
        End If
    End Sub

    Private Sub client_TransferProgress(ByVal Sender As tcpConnection, ByVal msgTag As Byte, _
        ByVal Percentage As Single) Handles client.TransferProgress
        Debug.Print("Transfer Progress: {0:p0}", Percentage)
        SetProgressBar(CInt(Int(Percentage * 100)), ProgressBar1)
    End Sub
#End Region 'Client Events

#Region "How to properly handle cross thread calls instead of ignoring them"
    Delegate Sub SetPictureCallback(ByVal mstream As System.IO.MemoryStream)

    Private Sub SetPicture(ByVal mstream As System.IO.MemoryStream)
        ' Thread-safe way to access the picturebox
        ' This isn't really needed because we are ignoring illegal cross thread calls.
        If Me.PictureBox1.InvokeRequired Then
            Dim d As New SetPictureCallback(AddressOf SetPicture)
            Me.Invoke(d, New Object() {mstream})
        Else
            PictureBox1.Image = Image.FromStream(mstream)
        End If
    End Sub
#End Region

#Region "Sub Procude"
    Delegate Sub VisibleControl(ByRef control As ProgressBar)
    Public Sub VisibleProgressBar(ByRef control As ProgressBar)
        If control.Value < 100 Then ' Status Loading
            control.Visible = True
            cmdGetPicture.Enabled = False
            cmdGetFile1.Enabled = False
            cmdGetFile2.Enabled = False
        Else                        ' Status Complete
            control.Visible = False
            cmdGetPicture.Enabled = True
            cmdGetFile1.Enabled = True
            cmdGetFile2.Enabled = True
        End If
    End Sub

    Public Sub SetProgressBar(ByVal IntPercent As Integer, ByRef control As ProgressBar)
        control.Value = IntPercent
    End Sub

    Private Sub SaveFile(ByVal FilePath As String, ByVal mstream As System.IO.MemoryStream)
        'save file to path specified
        Dim FS As New FileStream(FilePath, IO.FileMode.Create, IO.FileAccess.Write)
        mstream.WriteTo(FS)
        mstream.Flush()
        FS.Close()
    End Sub
#End Region

    Public Event StringReceived(ByVal Client As tcpConnection, ByVal msgTag As Byte, ByVal message As String)
    Private Sub onStringReceived(ByVal Sender As tcpConnection, ByVal msgTag As Byte, ByVal message As String)
        GetFile = message
        Debug.Print(message)
    End Sub
End Class

แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2013-04-23 22:41:36 By : Giguntic
 


 

No. 5



โพสกระทู้ ( 52 )
บทความ ( 0 )



สถานะออฟไลน์


ใครพอจะอธิบาย Concept ลำดับขั้นตอนในการใช้งานเป็นแชทได้จะเป็นพระคุณเลยครับ
เพราะผมคิดว่ามันคงผิดที่ผมใช้ไม่เป็นเลยใช้ผิดลำดับคอนเซ็ปมัน จริงๆมันน่าจะเป็นตามรูปนี้

3

แต่จาก Class TcpConnection.vb เท่าที่ผมเข้าใจคือ
Server มันให้ New Class แบบที่แรก แล้วต้อง Listener รับการเชื่อมต่อจากไคลเอนต์ด้วย
Code (VB.NET) จากใน TcpConnection.vb
Public Sub New(ByVal client As TcpClient, ByVal PacketSize As Int16)
034.'instantiates class for use in server

Client มันให้ New Class แบบที่สอง
Code (VB.NET) จากใน TcpConnection.vb
042.Public Sub New(ByVal IPServer As String, ByVal Port As Integer)
043.'instantiates class for use in client

แต่ผมก็ได้ลองไล่โค๊ดดูแล้วก็ไม่เห็นว่า Server มันยังไม่มีการนิวคลาสแบบแรกเลย
ผมก็เลยไปนิวคลาสเพิ่มใหม่เองจากใน frmServer.vb
Code (VB.NET) จากใน frmServer.vb
061.serverSend = New tcpConnection(requestor, PACKET_SIZE)

แต่พอผมนิวคลาสตัวนี้ปุ๊บ ฝั่ง Server ก็รับ message จาก Client ไม่ได้เลย
Code (VB.NET) จากใน TcpConnection.vb
158.RaiseEvent StringReceived(Me, passThroughByte, strX) 'มันโดดข้ามการทำงานตรงนี้ไปเลย 

ผมก็ไม่รู้ว่าผมผิดที่ตรงไหน ใครพอจะชี้แนะผมได้บ้างครับ จะขอบพระคุณมากเลยครับ


ประวัติการแก้ไข
2013-04-24 11:55:49
2013-04-24 16:11:11
แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2013-04-24 11:46:41 By : Giguntic
 


 

No. 6



โพสกระทู้ ( 52 )
บทความ ( 0 )



สถานะออฟไลน์


T-T ไม่มีใครช่วยชี้แนะเลย
ตอนนี้ ผมลองจนสามารถส่งข้อมูลไปกลับแบบ 2ทางได้แล้วครับ เป็นเพราะผมโง่เองใช้ไม่เป็นจริงๆ
แค่เปลี่ยนนิดเดียวในไฟล์ frmServer.vb
Line 44, 45 เปลี่ยนจาก serverSend เป็น listener แล้วใช้ Method BroadcastFile ใน clsListener.vb เอา
Line 61 เอาออก
แค่นี้ก็ส่ง message ไปกลับกันได้ทั้ง 2 ฝั่งแล้ว

แต่ตอนนี้ยังติดอยู่ปัญหาเดียวคือ วนลูปส่งไฟล์ต่อเนื่องไม่ได้ message จะติดอักขระแปลกๆพ่วงท้ายมา แก้ไม่ถูกจริงๆครับ
แต่คิดว่าปัญหาน่าจะอยู่ในไฟล์ tcpConnection.vb

แต่ไม่รู้ว่าเป็นที่ เมธอด ReceiveOneByte หรือ SendFile เพราะถ้าไม่ใช้ SendFile ก็สามารถวนลูปส่งข้อความได้ไม่ค้างครับ ใครจะช่วยชี้แนะผมได้บ้างครับ


ประวัติการแก้ไข
2013-04-25 22:14:01
2013-04-25 22:28:01
2013-04-25 22:44:10
แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2013-04-25 00:07:47 By : Giguntic
 

   

ค้นหาข้อมูล


   
 

แสดงความคิดเห็น
Re : TcpListener multiple send file ดีบั๊กสเต็ปทำงานได้แต่พอรันจริงไม่ได้
 
 
รายละเอียด
 
ตัวหนา ตัวเอียง ตัวขีดเส้นใต้ ตัวมีขีดกลาง| ตัวเรืองแสง ตัวมีเงา ตัวอักษรวิ่ง| จัดย่อหน้าอิสระ จัดย่อหน้าชิดซ้าย จัดย่อหน้ากึ่งกลาง จัดย่อหน้าชิดขวา| เส้นขวาง| ขนาดตัวอักษร แบบตัวอักษร
ใส่แฟลช ใส่รูป ใส่ไฮเปอร์ลิ้งค์ ใส่อีเมล์ ใส่ลิ้งค์ FTP| ใส่แถวของตาราง ใส่คอลัมน์ตาราง| ตัวยก ตัวห้อย ตัวพิมพ์ดีด| ใส่โค้ด ใส่การอ้างถึงคำพูด| ใส่ลีสต์
smiley for :lol: smiley for :ken: smiley for :D smiley for :) smiley for ;) smiley for :eek: smiley for :geek: smiley for :roll: smiley for :erm: smiley for :cool: smiley for :blank: smiley for :idea: smiley for :ehh: smiley for :aargh: smiley for :evil:
Insert PHP Code
Insert ASP Code
Insert VB.NET Code Insert C#.NET Code Insert JavaScript Code Insert C#.NET Code
Insert Java Code
Insert Android Code
Insert Objective-C Code
Insert XML Code
Insert SQL Code
Insert Code
เพื่อความเรียบร้อยของข้อความ ควรจัดรูปแบบให้พอดีกับขนาดของหน้าจอ เพื่อง่ายต่อการอ่านและสบายตา และตรวจสอบภาษาไทยให้ถูกต้อง

อัพโหลดแทรกรูปภาพ

Notice

เพื่อความปลอดภัยของเว็บบอร์ด ไม่อนุญาติให้แทรก แท็ก [img]....[/img] โดยการอัพโหลดไฟล์รูปจากที่อื่น เช่นเว็บไซต์ ฟรีอัพโหลดต่าง ๆ
อัพโหลดแทรกรูปภาพ ให้ใช้บริการอัพโหลดไฟล์ของไทยครีเอท และตัดรูปภาพให้พอดีกับสกรีน เพื่อความโหลดเร็วและไฟล์ไม่ถูกลบทิ้ง

   
  เพื่อความปลอดภัยและการตรวจสอบ กระทู้ที่แทรกไฟล์อัพโหลดไฟล์จากที่อื่น อาจจะถูกลบทิ้ง
 
โดย
อีเมล์
บวกค่าให้ถูก
<= ตัวเลขฮินดูอารบิก เช่น 123 (หรือล็อกอินเข้าระบบสมาชิกเพื่อไม่ต้องกรอก)







Exchange: นำเข้าสินค้าจากจีน, Taobao, เฟอร์นิเจอร์, ของพรีเมี่ยม, ร่ม, ปากกา, power bank, แฟลชไดร์ฟ, กระบอกน้ำ

Load balance : Server 02
ThaiCreate.Com Logo
© www.ThaiCreate.Com. 2003-2024 All Rights Reserved.
ไทยครีเอทบริการ จัดทำดูแลแก้ไข Web Application ทุกรูปแบบ (PHP, .Net Application, VB.Net, C#)
[Conditions Privacy Statement] ติดต่อโฆษณา 081-987-6107 อัตราราคา คลิกที่นี่