NETWORK APPLICATION DESIGN
USING TCP/IP PROTOCOL
IN WINDOWS
BY CHUN WANG
Submitted in Partial Fulfillment of the Requirement for the
Degree of Master of Science
in Computer and Information Sciences
Approved By:_________________________
Professor C.Y. Hsieh
Knowledge Systems Institute
Skokie, IL, USA
August 1997
ACKOWLEDGMENT
I would like to express my thanks to Professor Cheng-Yuan Hsieh, my advisor, not only for his kindly help on this project, but also for the courses that he taught which provide a foundation for this project.
I also would like to offer my thanks to Mr. Jiaping Fu for his innovative ideas concerning programming which were helpful in completing this project.
I also would like thank Dr. David G. Singer for proof reading this thesis.
ABSTRACT
One of the challenges in computer programming is internetworking with TCP/IP, not only because of its popularity, but also because of its complexity.
This thesis attempts to explain the way the socket programming interface works on TCP/IP and the way the Visual Basic socket custom control works on TCP/IP within 32-bit Windows environment. Finally the thesis presents an object, the Chinese Chess game. Implemented with
Visual Basic and a socket custom control, the project works in client/server model, on TCP/IP network protocol, under 32-bit Windows environment. You may find that using Visual Basic socket custom control to implement an application on TCP/IP is not very difficult.
CONTENTS
Chapter 1 Introduction 6
Chapter 2 Introduction of TCP/IP 7
2.1 TCP/IP Layering 7
2.2 TCP/IP Addressing 10
2.3 Client/Server Model in TCP/IP 12
Chapter 3 The Socket Programming Interface 17
3.1 Berkley Socket Calls 18
3.1.1 Socket TCB 18
3.1.2 Client/Server Application 19
3.3 The Visual Basic Socket Custom Control 26
Chapter 4 The Implementation of "Chinese Chess" Program 31
4.1 Design Consideration 32
4.2 The Scheme of The Program 33
4.3 Analysis of The Communication Code 37
4.3.1 Establishing The Connection 37
4.3.2 Data Exchanging 39
Chapter 5 Running The "Chinese Chess" : A Scenario 43
Chapter 6 Conclusion 46
References 47
Appendix
1. Rules of playing "Chinese Chess" 48
2. Parts of The Source Code 52
CHAPTER 1 Introduction
As the Internet is becoming increasingly important part of our daily life, the importance of TCP/IP has become known to more and more people since it is the protocol Internet was built on. For computer people the socket is almost the synonym of TCP/IP because it is a major programming interface for TCP/IP protocol. The Window Socket API provides the binary-compatible network programming interface for Microsoft Windows. The Microsoft Foundation Class Library (MFC) supports programming with the Windows Sockets API by supplying two classes: CAsyncSocket, and its derivative, CSocket. Many Visual Basic vendors provide their TCP/IP solution with a variety of socket custom controls based on these classes for about a million VB programmers in the world. In my game application program, Chinese Chess, I use the newest version of the socket custom control derived from CAsyncSocket class by Mabry Software. This custom control allows my application to run well on both Windows95 and Windows NT.
* * * *
The central ideas of this paper are in chapter three and four. Since the socket programming interface is closely related with TCP/IP, readers who have difficulty understanding chapter three would do well to go back to chapter two.
CHAPTER 2 Introduction of TCP/IP
The TCP stands for Transmission Control Protocol. The IP stands for Internet Protocol. They provide reliable, connection oriented, peer to peer communications. Many services such as FTP, Telnet, email and WWW can be provided by implementation of TCP/IP.

The TCP/IP provides connecting equipment from different vendors, running over deferent media and data link uniting the networks into Internet, enabling new networks plug into Internet without interruption of service to the rest of the network. The porting devices such as bridges, multiplexes and switches support the TCP/IP to fulfill these functions.
In order to exchange data over Internet, many procedures must be carried out:
1. Package the data
2. Determine the path through which the data will flow
4. Regulate the rate of data transfer according to the available bandwidth and capacity of the receiver to absorb the data
5. Assemble incoming data so that it is in sequence and there are no missing pieces
6. Checking the incoming data for duplicated pieces
7. Notify the sender of how much data has been received safely
8. Deliver data to the right application
9. Handle error on problem events
All of the above requirements cause the communication software to become quite complicated. To ease the implementation, these procedures are laid on different layers as in the following figure, each of which carries its own duty. The two applications exchange the data through these layers of the network structure.

The Physical Layer deals with physical media, connectors, and 0, 1 signals. The example of it is the network interface card which implements the physical layer functions.
At Data Link Layer, the data is organized into units called frames, which have a header and a trailer. The header consists of the address and control information. If the data transmission is within a Local Area Network(LAN), the addresses are the identifier of the source and destination network interface card. If the transmission is over the LAN, the address would be the identifier of the frame relay circuit. The trailer is used for error detection.
The function of IP(Internet Protocol) is to route data between network systems in the Internet. The IP header contains the IP addressing information used to examine the destination address of the data. Data may traverse a single link or be relayed across several links in traveling to its destination. The data is carried in units called datagrams. The IP layer is connectionless because every datagram is routed independently and IP does not guarantee the reliability of the delivery of the datagrams in correct order.
The TCP(Transmission Control Protocol) provides reliable data connection services to applications. It guarantees that data is delivered error-free, i.e., in sequence, no missing data, and no duplication of data. TCP fulfills this function by adding the header to form a segment and examines the header when it is delivered. The segment is the delivered data unit in the TCP layer. TCP is one of the layers that interfaces with applications.

UDP(User Datagram Protocol) passes the stand along messages for the applications. It accepts incoming datagrams from IP and determines which application is recipient. It also passes the outgoing messages from application to IP. It is connectionless service.
When the bare data pass through the layers downward, the corresponding header or trailer will be added to them at each layer; When the data flow upward, the corresponding header or trailer will be tripped off at each layer.
2.2 TCP/IP Addressing
There are two kind of addresses for TCP/IP protocol to identify the machine,. One is domain address, such as "jupiter.ksi.edu". The other is IP address, such as "205.212.86.120". Both kinds of addresses can identify the machine uniquely. The domain address is easy to remember. But for routing over Internet, the data is guided by the IP address. The domain address can be translated into IP address. In the Internet address family, some addresses are reserved for special purposes. They are special addresses.
There is an interesting address 127.0.0.1, called "loopback", which enables client and server to work in the same host. The characteristic of this address makes it easy to develop client/server application in a stand along computer.
To connect, the applications must identify each other not only by IP address of the machines they are sit on, but also by the port numbers which are used to identify the processes or services. The available port numbers range from 0 to65,535, of which numbers 0 to 1023 are reserved for well known services, such as FTP and Telnet. The rest of the numbers are enough for user defined applications.
That the client uses socket address (i.e. the combination of IP address and port number) to identify its connection to the server makes it easy for the server to keep track of multiple client connections.

2.3 Client/Server Model in TCP/IP
TCP/IP is normally used to implement the client/server applications, such as World Wide Web(WWW), terminal login, file transfer etc. In client/server model, the server application listens in on the incoming connection request from the client application passively, while the client application initiates the TCP connection actively.
How do two applications start a connection? Before a communication, each application calls its subroutine that creates a block of memory. That memory will be used to store the TCP and IP parameters for the connection, such as socket addresses, current sequence number, initial IP Time-To-Live value etc. On the server side, the server application waits for incoming clients. On the client side, the client which wants to access the server will issue the connecting request by identifying the server's IP address and port number.
The connecting procedure is called a three-way handshake because three messages(SYN, SYN and ACK) are exchanged to set up the connection.
The following figure shows a simple connection scenario.

The steps are:
1. The server initiates and is ready to accept connections from the clients ( called passive open ).
2. The client asks TCP to open a connection to a server at a given IP address and port number ( called active open ).
3. The client TCP picks an initial sequence number #1000 .
The client TCP sends a synchronize segment( SYN ) carrying the sequence number, the size of the receive window (4K bytes), and the size of the biggest segment that client can receive(1460 bytes).
4. When the SYN arrives, the server TCP picks its initial sequence number #3000 ,. sends a SYN segment containing its initial sequence number #3000 , a ACK #1001 meaning that the first data byte sent by the client should be numbered #1001, the size of receive window (4K bytes), and the biggest segment that it can receive(1024 bytes).
5. When the client TCP receives the server's SYN/ACK message, the client TCP sends back an ACK #3001, meaning that the first data byte sent by the server should be numbered #3001.
6. The client TCP notifies its application that the connection is open.
7. When the server TCP receives the client TCP's ACK, the server TCP informs its application that the connection is open.
The TCP's data transfer begins at completion of the three-way handshake. The following figure shows the scenario of data exchange. We suppose that the segment size is 1000 bytes.

1. The first segment sent by the client contains bytes #1001 to #2000. The ACK announces that 3001 is the sequence number of the next byte expected from the server.
2. The server responds with a segment that contains 1000 bytes of data( start at #3001 ). The ACK indicates that bytes #1001 to #2000 have been received in perfect condition, so the sequence number of the next byte expected from client is #2001.
3. Next, the client sends segments start at bytes 2001,3001,4001 in quick succession. There is no wait for ACK if partner has unused buffer space available.
4. The server returns a ACK without data accompanied in the segment, indicates that all of the segments have been received perfectly.
Similar to connection establishment, the connection termination is carried out by tree-way handshake too. Either side can launch the close. It is very polite:
A: "I am finished. I have no more data to send."
B: "OK."
B: "I am finished too."
A: "OK."
Following figure illustrates the closing steps:

The steps are:
1. The server application tells TCP to close the connection.
more data to be sent.
3. The client TCP sends an ACK of FIN segment.
4. The client TCP notifies its application that the server wishes to close.
7. The server TCP receives the client's FIN, and responds with an ACK.
8. The server TCP notifies its application that the connection is closed.
CHAPTER 3 The Socket Programming Interface
The TCP/IP defined the rules for exchanging data across a network. Between TCP/IP and application, the socket programming interface provides that applications can communicate with each other over networks.
Originally, socket was included in the BSD version of Unix operating system. After a number of improvements, it can be used on TCP and many other protocols and platforms, making it almost universally available. The Windows Sockets API, for example, based on Berkley Socket, was developed to standardize TCP/IP programming interface under Windows environment.
Windows Socket is the extension of Berkley Socket. Several sets of socket calls make it suitable for both Win16 and Win32. Targeted for Windows NT and Windows 95, The MFC classes, CAsyncSocket and CSocket also support asynchronous model of communication.
Many Visual Basic vendors have developed Windows Socket Custom Controls. These VBX or OCX files are derived from Windows Socket API and MFC classes. They greatly extend the Internet functionality of Visual Basic. In my Visual Basic application, I have employed one of them.
One of the purposes of Windows Socket is to ease porting of code between Berkley and Windows environment. For better understanding, let us begin our discussion with generic Berkley Socket calls.
3.1 Berkley Socket Calls
Knowing what information a program needs to communicate over a TCP/IP network, we now can discuss how to create a socket. However, creating a socket by itself doesn't let you exchange information, just like having a telephone in your house doesn't mean that you can talk to someone by simply taking it off the hook. You need to establish a connection with another program, just as you need to dial a telephone number, and to do this you need the socket address of the application to which you want to connect. This address consists of two key parts: the IP address and the service port number.
3.1.1 Socket TCB
The socket() call prepares for communication by creating a Transmission Control Block(TCB). In some places this process is called "create socket". The socket call returns a integer called a Socket descriptor which is used to identify the communication in subsequent operations. Many parameters are included in TCB. Here we list some of them and their example values in the parentheses to give you the ideas of information needed for TCP session:
Address Family (AF_INET) // Select Internet address family
Local IP address (212.205.86.120)
Local port (10000)
Protocol (TCP or UDP)
Remote IP address (212.205.86.135)
Remote port (10001)
Send buffer size (1024)
Receive buffer size (1024)
Current TCP state (on receive, on send , on accept , on close, on connect )
Current retransmission time out value
Maximum send segment size
Maximum receive segment size
Sequence number of last byte that was ACKed
Sequence number of next byte to be sent
3.1.2 Client/Server Applications
When two programs wish to use TCP to exchange data, one of the programs must assume the role of the client, while the other must assume the role of the server.
The server application creates a socket and passively listens in to the requests of incoming connection from clients with four calls:
socket() In this call, the server identifies the type of communication(TCP in this case) and the local system creates an appropriate TCB data structure for communication and returns a socket descriptor.
bind() In this call, the server establishes the local IP address and port number that it wants to use. Sometimes the server may have multiple IP addresses. The server may specify one IP address or else indicate that it is willing to accept connections arriving at any local IP address. The server may ask for a specific port number or else just let the bind() call to obtain a free port number that it can use.
listen() In this call, the server sets up the length of the client queue (ranges from 1 to 5).
accept() In this call, the server is ready to accept client connections. If the queue is not empty, the first client connection is accepted. The accept() call creates a new TCB that will be used for this current client connection and returns a new descriptor to the server ( the original descriptor was given to the socket communicating with current client) which will enable server to accept next client’s connection .
On the other side, the client application initiates what is called an active open. It creates a socket and actively attempts to connect to a server program with two calls:
socket() In this call, the client identifies the type of communication(TCP in this case). The local system creates an appropriate TCB data structure for the communication and returns a local socket descriptor.
connect() The client identifies a server's IP address and port number. TCP will attempt to establish a connection with the server.
If the client wishes to specify exactly which local port it want to use, the client must call bind() before calling connect(). If the port number is available, the bind() will assign it to the client.
If the client does not call bind() to ask for a port number, the connect() call will assign an unused port number to the client. The port number will be entered into TCB.
Some other calls are explicit:
send() Writes a buffer of data to the socket. write() may be used for alternative.
recv() Receives a buffer of data from socket. read() may be used for alternative.

When the client initiates a connection, the server is notified that some process is attempting to connect with it. By accepting the connection, the server completes a logical communication pathway between the two programs. It is important to note that the action of accepting a connection creates a new socket, which inherits the original TCP. The original socket remains unchanged so that it can continue to be used to listen in to additional connections from other clients. When the server no longer wishes to listen in to connections, it will close the original passive socket.
To review, there are several significant steps that a program which uses TCP must take to establish and complete a connection. The server side program should follow these 7 steps:
1. Call socket() to create master TCB and return an integer socket descriptor which will identify TCB for future calls.
2. Enter the server’s local socket address which includes IP address and port number into a data structure.
3. Call bind() which copies the local socket address data structure into the TCB.
4. Call listen() to set up a queue( ranges from 1 to 5) which can hold several clients.
5. Wait for clients. When a client arrives, creates a new TCB for the client. The new TCB is constructed by making a copy of the master TCB and write the client's socket address and other client parameters into the TCB. This process is done by calling accept().
6. Create a child process to serve the connected client. The child will inherit the new TCB and handles all further communication with the client and wait to receive and send the messages from and to client by calling recv() and send().
7. When server finishes its service to client, it closes the socket by calling close(), which will terminate the conversation.
In the case of the client, five steps should be taken:
1. Creates a TCB by calling socket() as in the case of server.
3. Establishes the connection with the server by calling connect(). If it didn't call bind() at the step 2, system will automatically assign a free port number to the client socket during this call.
4. Sends and receives information by calling send() and recv().
5. Closes the socket when service is finished, by calling close().
3.2 Windows Socket API and MFC CAsyncSocket Class
Windows Socket was popularized from the Berkley Socket, it is usable on Windows 3.0 and later versions. In other words, it provides Windows socket applications and implementations on both 16-bit and 32-bit operating systems.
The current widely used Windows Socket version is 1.1. For 16-bit application, the DLL file it provided is winsock.dll; For 32-bit one, it provides wsock32.dll. Both of them share the header file winsock.h. Both of winsock.dll and wsock32.dll take same parameters in socket implementation. The difference between them is that the integer parameters are 16 bits or 32 bits.
The Windows Socket 2 adds more functionality to Windows Socket 1.1. Its DLL file is ws2_32.dll, and header file is winsock2.h. So far, it is only available on Windows NT 4.0.
3.2.1 Windows Socket API
It is important to note that before make Windows Socket API calls, you should call WSAStartup() first. This function initializes the Windows Socket’s DLL file version. When you finish Windows Socket calls, the last call should be WSACleanup(), this function frees up the resources in DLL file. These two functions should be balanced with each other, as If and End If in Basic language.
The most important function that Windows Socket extends from Berkley Socket is WSAAsyncSelect(). This function can respond to several events that might happen during the coarse of communication. These events are:
FD_READ : Incoming data in Socket buffer is available for reading.
FD_WRITE: The Socket buffer is available for writing.
FD_OOB : The Out Of Band message is available to read.
FD_ACCEPT: A client's request for a connection has arrived.
FD_CONNECT: A client's attempt for a connection to a server has completed.
FD_CLOSE: The socket has been closed by the partner station.
FD_ALL_EVENTS: All of the above events.
By setting the bits in its parameter, WSAAsyncSelect() knows to which events it is going to respond.
The macro WSAGETSELECTEVENT() reports the emerging events.
What would we do if an event appears repeatedly or periodically? it is not necessary to reissue the WSAASelect() function. It is automatically reactivated in program when you call the enabling function.
In Windows Socket, WSAAsyncSelect() is very powerful function, which provides implicit multithreading and lets the socket automatically buffer the data for your requesting asynchronous recv() call, thereby leaving very little coding work for the programmers. The MFC CAsyncSocket class was built on top of it.
3.2.2 MFC CASyncSocket Class
Microsoft Foundation Class Library(MFC) provides two socket classes. One is ASyncSocket, The other is Csocket, derived from ASyncSocket. ASyncSocket class is thinly wrapped from Windows Socket API. As a class, it is also derived from Cobject class. From the point of view of the user, this class is at relatively low level, but it provides good flexibility. This class is declared in the header file afxsock.h and many methods are implemented as inline calls in the file afxsock.inl. Since there is no DLL file associated with this class. To use it, you need to call AfxSocketInit() first instead of WSAStartup() as in the case of Windows Socket API. Then you need to call the constructor of the class, followed by the create() member function to create a socket. Calling the destructor of this class will automatically call the close() member function and will close the socket.
This class includes almost all the functions that Windows Socket API has. It provides asynchronous processing as its class name implies. To use the services of CAsyncSocket, call the AsyncSelect() method to declare the events you are interested in. Only one argument is needed, the notification flag.
BOOL AsyncSelect ( long lEvent =
FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT |
FD_CONNECT | FD_CLOSE );
In response to the event flag , the class has a set of methods to handle the events.
CAsyncSocket Method Event flag
OnReceive FD_READ
OnSend FD_WRITWE
OnOutOfBandData FD_OOB
OnAccept FD_ACCEPT
OnConnect FD_CONNECT
OnClose FD_CLOSE
These methods have empty implementation so you need to override them to make them active. These methods play important roles in ASocket Visual Basic custom control.
3.3 ASocket Visual Basic Custom Control
ASocket VB custom control was derived from MFC ASyncSocket class by Mabry Software. It has VBX and OCX versions, supporting 16-bit and 32-bit Visual Basic respectively. Now let's take a near look at this control.
Property Description
Action To set the control to execute specific method. The value could be set to one of nine methods of this control.
BroadCastEnabled To be used for broadcast packet transmission
BytesSent The number of bytes of data remains in the send buffer
ErrorNumber Returns Last error code defined in Windows Socket
EventMask Enables the control's event by setting each bit corresponding
to the event which could be fired in application
KeepAliveEnabled Causes the keep session alive message to be sent to partner
LingerEnabled * Affects the way of closing socket
LingerMode * Affects the way of closing socket
LingerTime * Affects the way of closing socket
Listening Return True if at listening state. It is read only property
LocalAdress IP address of the Socket
LocalPort Port number of the Socket
OutofBandEnabled Enables out-of-band data on stream socket
ReceiveBuffer The buffer for data received by receive method
ReceiveBufferSize Sets the size of the socket's receive buffer
ReceiveTimeout The maximum number of seconds to wait to receive data.
RemoteAddress Address of remote socket
RemoteName Name of remote socket ( such as ftp.microsoft.com )
RemoteNameAddrXlat Enables to Translate domain address to IP address via DNS
RemotePort Specifies the port number of the remote socket
ReuseAddressEnabled Enables other sockets to use this local address
SendBuffer The buffer for writing the data into socket
SendBufferSize Sets the size of the socket's send buffer
SendTimeout The maximum number of seconds to wait to send data
Socket The Socket handle used for OnAccept event
SocketAddress The local socket's IP address
SocketPort The local port number available after Connect method
SocketType Stream Socket or Datagram Socket TCPNoDelayEnabled **Disables the Nagle delay algorithm when set to True
Version Shows the version of the ASocket control
* The semantics of Close method are affected by the LingerEnabled, LingerMode, and
LingerTime properties.
If the LingerEnabled property is False, then Close will return immediately. However,
any data queued for transmission will be sent, if possible, before the underlying socket is
closed. This is also called a graceful disconnect.
If LingerEnabled is True and if LingerMode is non-zero, the socket will close gracefully.
Control will return from the call after the socket finishes closing, if LingerTime is non-zero.
If LingerMode is zero or LingerTime is zero, the socket will be closed immediately.
** The Nagle algorithm is used to reduce the number of small packets sent by a host by
buffering unacknowledged sending data until a full-size packet can be sent. However, for
some applications this algorithm can impede the performance, and NoDelayEnabled can be used to turn it off.
Events Description
OnAccept Fired when server socket gets a client socket’s connection request
OnClose Filed when its partner closes the socket
OnConnect Fired when client socket ‘s connection is established
OnOutOfBandData Fired when the out-of-band message is received
OnReceive Filed when socket has the data available to be read
OnSend Fired when socket is ready to send data
Methods Description
Bind Associates local address with socket
Close Closes a socket
Connect Establishes a connection to server
Create Creates and opens a socket
Listen Enables socket to listen in to incoming connection requests
Receive Receives a buffer of data from socket
ReceiveFrom Receives a datagram and stores the source address.
Send Sends a buffer of data to the connected socket
SendTo Sends datagram to a specific remote socket
These 30 properties, 6 events and 9 methods are special to ASocket custom control. We will discuss how to apply this control in an application in the next chapter.
CHAPTER 4 The Implementation of "Chinese Chess" Program
We have discussed TCP/IP and Socket programming interface. Now it is time to introduce you to the "Chinese Chess" game, a TCP/IP application. This application employs a Windows Socket custom control to provide two playing chess game over networks.
The Chinese Chess game, which is more than two thousands years old, is the most popular game in China. Even now, there are still hundreds of million of Chinese Chess lovers in China. Many Chinese Chess game software can now be found on the Internet. But so far, it is hard to find one that provides for two parties playing over Internet and that works on Windows

Figure 4-1 Chinese Chess, 32 pieces on Chinese Chess board
platform.
4.1 Design Consideration
The objective of this program is to provide an interesting game for the network users, no matter whether they are professionals or beginners. To play Chinese Chess, the players have to follow the rules of this game. In this program, it is the player's responsibility to follow these rules. The beginner can refer to the rules of this game in the Appendix.
The chess game has 32 pieces, 16 pieces for each side, ranged on a 9 by 10 points chess board. To play the game remotely, the information about pieces on the board needs to be exchanged between the two partners. This information consists of the Left property, the Top property and the Tag property of the piece controls( Actually they are image control ). The Left property and the Top property represent X axis and Y axis coordinate of the piece on the board. The Tag property represents the groups of 32 pieces. The two groups, each with 16 pieces, appear in red and blue colors respectively, represent two sides of the game. When playing the game, the two players can only manipulate one group of pieces, either red or blue. Each group equally have 7 kinds of pieces, they are : the king or general, the guards, the ministers, the cannons, the chariots, the horses and the soldiers. Each of them has its own rules of movement. The objective of playing game is to win by checkmate and that may take some time and many steps.
This program provides graphic interface which represents the information of the pieces on the board and data communication tools which exchanges the information of the moving pieces.
The game won't tolerate any wrong information being exchanged since that would lead to player’s incorrect decision when manipulating pieces and also more incorrect information may follow. Therefore, the reliability of data exchange is very important for the success of this program.
To guarantee the reliability of data exchange, this application applies stream socket on TCP/IP. The stream socket is known as connection-oriented. It guarantees in order, no-missing, no duplication of data transmission. The program requires that the transmitted data include the data about all the pieces. In this way, no matter how many steps you have made with your pieces, both sides have identical data. The correctness of these data on both sides is thereby guaranteed.
4.2 The Scheme of The Program
When started, the program first loads the frmConnect form. This form prompts you to select either "To Connect as a Server" option or " To Connect as a Client" option. This application uses client/server model to establish the connection between the two partners. One of peers can select one of the options, and his partner can select the other.
Whatever you select, each of the peers needs to fill in the local IP address and remote IP address in the text boxes of the forms. When he finishes, the server must first click the OK button to passively listen in to the client’s connection request. Only after the server finishes this step can the client click the OK button to connect to the server. If the connection is established successfully, the frmConnect forms will be disappeared and be replaced with the frmChess forms on the screens of both stations. On the frmChess forms, both players will be prompted to select who will launch the first step by checking an option in "First Go" frames. According to the player’s selection, the appearance of the label "Your turn" tells the player that who will be the one to make the next step.
By the direction of "Your turn" lable, two player take turns moving the pieces. Each time, only one piece can be moved and must follow the rules of the game. Each movement of a piece will fire the send() call which puts the updated data of pieces into socket. The arriving data will notify the socket by firing OnReceive event and this event will call recv() to get the data from socket.
When you want to finish the game, click the Exit button, the program will first issue the close() call. This call informs the partner to close its socket. Only after sockets on both sides are closed, will both applications be closed.
The following figure illustrates the scheme of the application.

Let’s examine some of the procedures in from frmChess .
This procedure also set up the initial position of 32 pieces.
If this piece dropping does not capture the other piece, the updated data of 32 pieces written into send buffer by calling senddata() and the data in the send buffer will be put into socket by calling ASocket.Send method. The procedure senddata () will be discussed in next section.
Recall that the Tag property of 32 pieces are included in the exchanged data. The value of the tag is a string used to identify the piece. The tags are divided into two groups, blue and red, headed by letters "B" and "R" respectively. If you drop a piece at the position where another piece is there and which is not with the same color as the dropped one, the "another piece" would be captured.
The following procedure fulfills this purpose. When a piece is dropped, the procedure first check the first letter of the Tag property of the dropped piece . If that letter is "R", you could not see the piece "blusol2" (blue soldier 2) again.
Sub blusol2_DragDrop (Source As Control, X As Single, Y As Single)
If Left$(Source.Tag, 1) = "R" Then
blusol2.Visible = False
Source.Move blusol2.Left, blusol2.Top
senddata
AsyncSocket.Send
Beep
label1.Visible = False
End If
The communication ability is the most important feature of this application. This feature is "played" by ASocket custom control.
When program is started, the first form appears on your screen is frmConnect . This form enables you to initiate the connection.
Before creating a socket, four properties need to be filled :
Local IP address
Local port number
Remote IP address
Remote port number
In this application, server’s port number is fixed to 10000 and client’s port number is fixed to 10001. Since there are 63K port numbers can be defined by users, it is safe to fix these two port numbers in the program.
What will happen if more than two pairs play the Chinese Chess games on network in the same time?
No problem! It is the combination of IP address and port number that identifies a process. There is no possibility of interference in this process.
After filling in socket addresses and selecting either "Connect as a Server or "Connect as a Client", as described in last section, you can click the "OK" command button. This button will create a socket and the socket address is bound on this socket.
Private Sub CmdOK_Click()
If Opt = 1 Then 'Connect as a server
AsyncSocket1.LocalPort = 10000
AsyncSocket1.LocalAddress = Trim(TxtLocalAddress.Text)
AsyncSocket1.RemotePort = 10001
AsyncSocket1.RemoteAddress = Trim(TxtRemoteAddress.Text)
AsyncSocket1.Create
AsyncSocket1.Action = ASocketBind
AsyncSocket1.Action = ASocketListen
End If
If Opt = 0 Then ' Connect as a client
frmChess.AsyncSocket.LocalPort = 10001
frmChess.AsyncSocket.LocalAddress = Trim(TxtLocalAddress.Text)
frmChess.AsyncSocket.RemotePort = 10000
frmChess.AsyncSocket.RemoteAddress = Trim(TxtRemoteAddress.Text)
frmChess.AsyncSocket.Action = ASocketCreate
frmChess.AsyncSocket.Action = ASocketBind
frmChess.AsyncSocket.Action = ASocketConnect
Unload Me
End If
End Sub
During initiating connection, the same application could be a server or a client. From above procedure you can find that the server creates the Socket in frmConnect form while client creates the Socket in frmChess form.
If as a server, the calls are:
AsyncSocket1.Action = ASocketCreate
AsyncSocket1.Action = ASocketBind
AsyncSocket1.Action = ASocketListen
The socket now is listening in to the client’s connecting request.
If as a client, the calls are:
frmChess.AsyncSocket.Action = ASocketCreate
frmChess.AsyncSocket.Action = ASocketBind
frmChess.AsyncSocket.Action = ASocketConnect
The client now is connecting to the server.
After server gets connection request from the client, the OnAccept event message comes up. In response to this message the server will activate the AsncSocket1_OnAccept() procedure.
Private Sub AsyncSocket1_OnAccept(ByVal SocketHandle
As Long, ByVal ErrorCode As Integer)
frmChess.txtSocketHandle = CStr(SocketHandle)
Unload Me
End Sub
In above procedure, the server socket in frmConnect form transfers its handle( the socket descriptor ) to a text box txtSocketHandle of the form frmChess . Later this handle will be assigned to the socket in frmChess form. The socket in frmChess is responsible for exchanging data with client socket. In this application, a server only communicate with one client. Therefore, it is not necessary to keep a listening socket after a connection has been established. We need to close this socket. The Unload statement autometically closes the socket in frmConnect form. The socket in frmChess will inherent the TCB from the closed socket in frmConnect form.
On client side, if the client gets successful connection with the server, it will unload the frmConnect form. The client has never used the socket in frmConnect form.
Private Sub AsyncSocket_OnConnect(ByVal ErrorCode As Integer)
Unload frmConnect
End Sub
4.3.2 Data Exchanging
The exchanged data are the data of 32 pieces (these pieces are picture controls) , each of them consists of values in Left, Top and Tag properties. Each property is given 10 bytes space. Total number of data to be exchanged is 960 bytes.
Recall that ASocket custom control is derived from CAsyncSocket, a thin wrapper of the Windows Socket API. It just performs the functionality of Windows Socket API. The only media that sockets on both sides used to exchange data are SendBuffer and ReceiveBuffer. That means to exchange data you need to write string to SendBuffer and to read string from ReceiveBuffer.
You can’t put the file or structured data into a buffer directly. You also can’t get the file or structured data directly from a buffer.
The solution in this application is concatenating all the exchanging data into a 960 bytes string before it is written to SendBuffer and chopping a 960 bytes string into 96 small strings after it is read from ReceiveBuffer.
The following procedure writes all data of 32 pieces into send buffer:
Private Sub senddata()
Dim string1, string2, string3 As String
Dim t As String
'Set the length of the strings
string1 = "0123456789"
string2 = "0123456789"
string3 = "0123456789"
‘ Write the data into string1, string2, string3
LSet string1 = blugun1.Visible
LSet string2 = blugun1.Left
LSet string3 = blugun1.Top
‘Write string1, string2 and string3 to AsyncSocket.SendBuffer,
t = t & string1 & string2 & string3
LSet string1 = blugun2.Visible
LSet string2 = blugun2.Left
LSet string3 = blugun2.Top
'Write string1, string2 and string3 to AsyncSocket.SendBuffer,
t = t & string1 & string2 & string3
. ‘ Here the information of other pieces are concatenated into t
.
.
t = t & string1 & string2 & string3
‘Indicates that 960 bytes has been written into SendBuffer
text6.Text = Len(t)
‘ Write the string t into SendBuffer
AsyncSocket.SendBuffer = t
End Sub
After this procedure is finished the text box text6 displays that 960 bytes will be written into send buffer.
In procedure Form_Dragdrop() and procedure Piece_Dragdrop(), senddata() is followed by Socket.Send() call.
.
.
senddata ‘Write data of pieces to send buffer
AsyncSocket.Send
Beep
label1.Visible = False ‘"Your turn" Label is invisible
End Sub
The arriving of data will activate the event OnReceive().
Private Sub AsyncSocket_OnReceive(ByVal ErrorCode As Integer)
AsyncSocket.Receive ‘Receive data from socket to ReceiveBuffer
Beep
receivedata ‘Read the data from buffer to 32 pieces
label1.Visible = True ‘ "Your turn" label is visible
End Sub
Following procedure will read the data from ReceiveBuffer to 32 pieces. It gets a 960 bytes string from ReceiveBuffer and chops it into 96 small strings. Finally, it assigns these strings into 32 pieces. These strings update the pieces’ location on the chess board. After these string are assigned to the properties of each piece, These pieces will be rearranged on the board automatically.
Private Sub receivedata()
Dim string1, string2, string3
Dim t As String
‘Read 960 bytes string from ReceiveBuffer
t = AsyncSocket.ReceiveBuffer
text5.Text = Len(t) 'The string length is 960 bytes
‘Read the first 10 bytes to string1
string1 = Trim(Left(t, 10))
‘ Write data in string to visible property of the piece
blugun1.Visible = string1 ‘ The Visible property has been assigned
‘Chop off the first 10 bytes from string t
t = Mid(t, 11)
string2 = Trim(Left(t, 10))
blugun1.Left = string2 ‘ The Left property has been assigned
t = Mid(t, 11)
string3 = Trim(Left(t, 10))
blugun1.top = string3 ‘ The Top property has been assigned
‘ Now the piece blugun1 (cannon) has
. ‘ gotten its new information
. ‘ Here other pieces get their new information
.
End Sub
CHAPTER 5 Running The "Chinese Chess" : A Scenario
1. When a program starts, the "Connecting" form (frmConnect) comes up. You need to fill in your local IP address and the Remote IP address which represents the machine you want to connect to.

Figure 5-1 The frmConnect form
2. Next, you need to select one option in the frame. You can select either "Connect as a Server" or "Connect as a Client". You just select one and let your partner pick the other. Be sure that whoever selects "Connect as a Server" must click the OK button first.
Only after the server clicks the OK button, can the client click the OK button. If the connection is established successfully, after the client clicks the OK button, the frmConnect form will disappear in seconds and this form will be replaced by a frmChess form which is a chess board.

Figure 5-2 The frmChess form
3. When the Chess board form shows up, you have to select who will take the first step in the "First Go" frame, just click one option and let’s your partner select the other .
4. Next, you can begin to play Chinese Chess. Who will be the next one to move the piece is decided by the appearance of the sign "Your turn". When "Your turn" sign appears on your board, you can move one piece only once.

Figure 5-3 "Your turn" sign appears on your board,
it is your turn to move a piece
5. To close the application, just click Exit button, the frmChess forms will disappear at both sides, no matter you are client or server.
CHAPTER 6 Conclusion
After a number of improvements by its vendor, the ASyncSocket custom control now is available for customers to extend the Internet functionality of their VB application on 16-bit and 32-bit Windows platforms. Compared with other Internet solutions, such as calling WinSock DLL, this Socket custom Control is easy to use because not only is it compatible with Visual Basic, but it also hides many coding details from customers. But for making better use of this custom control, you still need to understand the ASyncSocket class and its members as well as underlying protocol.
This Chinese Chess program provides two basic features for the game: the graphic interface and the communication tool. For people who are familiar with the Chinese Chess game, these features meet the principle requirements. But if you consider there are many people who are not familiar with this game and want to play it, you may want the program which provides a third feature, the rules. Actually coding the rules is a big job. There are 32 pieces of 7 kinds, which means 7 kinds of rules, each of which relates with other pieces and their locations at the board. To commercialize this application, I would like some one else to implement the rules for it.
REFERENCES
ISBN 0-201-48930-9
Addison-Wesley Publishing Company, ISBN 0-201-62278-5
1995 SAM Publishing, ISBN 0-672-30620-4
"Windows Sockets in MFC: Overview"
"Network Services Overview"
Microsoft Knowledge Base for Win32 SDK
APPENDIX 1 The rules of Chinese Chess
Object of The Game
Players move and capture as in chess. Winning is by checkmate or stalemate. That is, a player loses if he cannot make a move without exposing his general or king to capture.
The Board
There are 90 points of play, arranged in 10 ranks or rows and 9 files or columns. The board has some special features: the two castles, which are nine-point squares defined by a large X, and the river, which separates the two halves of the board. These features affect some of the pieces.

Moves of The Pieces
General ![]()
One
point along a rank or file; may not leave the castle.
Guard ![]()
One
point along a diagonal within the castle. Can visit only five different
points.
Minister ![]()
Always
two points along a diagonal; may not cross the river
or leap a piece. Can visit only seven different points.
Horse ![]()
One
point along a rank or file, then one point diagonally. May ot leap a piece.
Chariot ![]()
Any
distance along a rank or file, without leaping. Just like a western rook.
Cannon ![]()
Ordinarily
moves like a chariot, but cannot capture unless it
leaps over a single piece of either color on the way to its target.
Soldier ![]()
One
point straight ahead until it has reached the far bank of the river; then
it may move one point straight forward or along a rank. Never moves diagonally
or backward.
As well as its regular move, the general has the theoretical power of attacking the opposing general along an open column, moving just like a chariot. Any move that puts the generals opposite one another along an open column is therefore equivalent to moving into check, and is illegal.
Note that only the chariot is exactly like its counterpart in chess. The horse is like the knight but must always take the "straight" part of its move first, and can be blocked by a piece of either color at the elbow of its path. The cannon cannot leap unless it is capturing, and cannot capture without leaping.
Hints on Playing Game
Don't rely too much on the knowledge of Western chess. Chinese Chess is a much more open, tactical game. With ready-cleared files that permit quick attacks by chariot and cannon, the most mobile pieces. Control of these open files, particularly those aimed at the enemy castle, is most important.
The cannon is an interesting piece. It can attack at a long range, but once is shot over the enemy line it may lose its efficacy and attacking power. An important thing to remember is that the cannon can pin two enemy pieces against their general - if either one moves out of the line, the general is put in check. With this in mind, many games begin with a cannon being moved to the center file. Some fascinating situations may develop when two or more enemy cannons line up against one another and begin a leapfrogging tactic.
The ministers, the guards, and for the most part the general itself are defensive pieces, except in those instances where they provide a screen for the cannon. But their constant presence in the home field provides chariots, cannons, and horses more freedom to attack. After
developing your pieces - getting the chariots onto open ranks and files, bringing the horses off the back row and deploying the cannons behind screens - move quickly against the enemy. There is no place in Chinese Chess for a tenacious, passive defense. It is impossible to build an impregnable, interlocked wall of men as you might do in Western chess - chiefly because of the very different nature of the pawns, or soldiers - and it is better to deploy your forces in an active, aggressive way.
Do not overlook the power of the promoted soldier. Once across the river this little piece triples in strength, and in many situations, especially close in on the castle, it can be as effective as a chariot. And don't forget the general's ability to close off a file to the opposing general -
a power that frequently clinches checkmate.
For purposes of evaluating trades, count a guard and a minister as two, cannon and horse as four, and chariot as eight. Trading a horse for a cannon may be a good idea early in the game, but becomes less wise as the board opens up and the cannon becomes relatively weaker. Soldiers start as one but can greatly increase in value depending on their position. In the early stages of the game, the enemy soldiers are temptingly exposed targets, but don't waste time on them: it is far more important to develop your major pieces and not lose the initiative.
Appendix 2 Part of code In Chinese Chess
2.1 Part of codes in frmConnect form
Begin AsocketLib.AsyncSocket AsyncSocket1
Left = 4560
Top = 1800
_Version = 327680
_ExtentX = 847
_ExtentY = 847
_StockProps = 0
ReceiveBufferSize= 8192
SendBufferSize = 8192
BroadcastEnabled= 0 'False
LingerEnabled = 0 'False
RouteEnabled = -1 'True
KeepAliveEnabled= 0 'False
OutOfBandEnabled= 0 'False
ReuseAddressEnabled= 0 'False
TCPNoDelayEnabled= 0 'False
LingerMode = 1 ‘ Smoothly closes the socket
LingerTime = 2
EventMask = 63
LocalPort = 0
RemotePort = 0
SocketType = 0
LocalAddress = ""
RemoteName = ""
RemoteAddress = ""
ReceiveTimeout = -1
SendTimeout = -1
End
Option Explicit
Dim Opt As Integer
Private Sub AsyncSocket1_OnAccept(ByVal SocketHandle As Long,
ByVal ErrorCode As Integer)
‘ Transfer the socket handle to the socket which will exchange data
‘ with clien
frmChess.txtSocketHandle = CStr(SocketHandle)
Unload Me
End Sub
Private Sub AsyncSocket1_OnClose(ByVal ErrorCode As Integer)
AsyncSocket1.Action = ASocketClose
‘ Available for multi-client
AsyncSocket1.Action = ASocketCreate
AsyncSocket1.Action = ASocketListen
End Sub
Private Sub CmdCancel_Click()
frmChess.AsyncSocket.LocalAddress = ""
frmChess.AsyncSocket.LocalPort = 0
frmChess.AsyncSocket.RemoteAddress = ""
frmChess.AsyncSocket.RemmotePort = 0
Unload Me
End Sub
Private Sub CmdOK_Click()
If Opt = 1 Then 'Connect as a server
‘ Server’s port number is 10000
AsyncSocket1.LocalPort = 10000
AsyncSocket1.LocalAddress = Trim(TxtLocalAddress.Text)
AsyncSocket1.RemotePort = 10001
AsyncSocket1.RemoteAddress = Trim(TxtRemoteAddress.Text)
AsyncSocket1.Create
AsyncSocket1.Action = ASocketBind
AsyncSocket1.Action = ASocketListen
frmChess.Caption = "Playing Chinese Chess Over Network ( Server )"
End If
If Opt = 0 Then ' Connect as a client
‘ Client’s port number is 10001
frmChess.AsyncSocket.LocalPort = 10001
frmChess.AsyncSocket.LocalAddress = Trim(TxtLocalAddress.Text)
frmChess.AsyncSocket.RemotePort = 10000
frmChess.AsyncSocket.RemoteAddress = Trim(TxtRemoteAddress.Text)
frmChess.AsyncSocket.Action = ASocketCreate
frmChess.AsyncSocket.Action = ASocketBind
frmChess.AsyncSocket.Action = ASocketConnect
frmChess.Caption = "Playing Chinese Chess Over Network ( Client )"
Unload Me
End If
End Sub
Private Sub OptClient_Click()
Opt = 0 ‘ If select Connect as a Client
End Sub
Private Sub OptServer_Click()
Opt = 1 ‘ If select Connect as a Server
End Sub
2.2 The codes in frmChess form. Here we don’t want to list the code for all 32 pieces. If the code concern pieces, we just list code for a piece "blue gun"(cannon) as a example. The code for other pieces are very similar.
Begin AsocketLib.AsyncSocket AsyncSocket
Left = 6480
Top = 4680
_Version = 327680
_ExtentX = 847
_ExtentY = 847
_StockProps = 0
ReceiveBufferSize= 8192
SendBufferSize = 8192
BroadcastEnabled= 0 'False
LingerEnabled = 0 'False
RouteEnabled = -1 'True
KeepAliveEnabled= 0 'False
OutOfBandEnabled= 0 'False
ReuseAddressEnabled= -1 'True
TCPNoDelayEnabled= 0 'False
LingerMode = 1
LingerTime = 2
EventMask = 63
LocalPort = 0
RemotePort = 0
SocketType = 0
LocalAddress = ""
RemoteName = ""
RemoteAddress = ""
ReceiveTimeout = 100
SendTimeout = 1
End
Begin VB.Menu mnuHelp
Caption = "&Help"
Begin VB.Menu mnuAbout
Caption = "About..."
End
End
End
Option Explicit
Dim top0, top1, top2, top3, top4, top5, top6, top7, top8, top9
Dim left0, left1, left2, left3, left4, left5, left6, left7, left8
Private Sub AsyncSocket_OnClose(ByVal ErrorCode As Integer)
AsyncSocket.Action = ASocketClose
Unload Me
End Sub
Private Sub AsyncSocket_OnConnect(ByVal ErrorCode As Integer)
Unload frmConnect
End Sub
Private Sub AsyncSocket_OnReceive(ByVal ErrorCode As Integer)
AsyncSocket.Receive ‘Receive data from socket
Beep
Timer1.Enabled = True
receivedata ‘To write received data into every pieces
cmdReceive.Enabled = True
label1.Visible = True ‘ your turn to move the piece
End Sub
Private Sub blugun1_DragDrop(Source As Control, X As Single, Y As Single)
If Left$(Source.Tag, 1) = "R" Then ‘If blue cannon is captured,
blugun2.Visible = False ‘you will not see it again.
‘ The piece will take the place of blue cannon.
Source.Move blugun2.Left, blugun2.Top
‘ Write the updated data of pieces into send buffer
senddata
‘ Socket get the data in send buffer.
AsyncSocket.Send
Beep
‘ Now you can’t move the piece.
label1.Visible = False
End If
End Sub
. ‘ Other pieces’ DagDrop procedures are here
.
.
Private Sub comExit_Click()
End
End Sub
Private Sub Form_DragDrop(Source As Control, X As Single, Y As Single)
Dim tx, ty
' Automatically puts the piece at the right position if not captures
‘ a piece
If (X - 290) <= left0 Then
tx = left0
ElseIf (X - 290) >= left8 Then
tx = left8
ElseIf Abs((X - 290) - left0) <= Abs((X - 290) - left1) Then
tx = left0
ElseIf Abs((X - 290) - left1) <= Abs((X - 290) - left2) Then
tx = left1
ElseIf Abs((X - 290) - left2) <= Abs((X - 290) - left3) Then
tx = left2
ElseIf Abs((X - 290) - left3) <= Abs((X - 290) - left4) Then
tx = left3
ElseIf Abs((X - 290) - left4) <= Abs((X - 290) - left5) Then
tx = left4
ElseIf Abs((X - 290) - left5) <= Abs((X - 290) - left6) Then
tx = left5
ElseIf Abs((X - 290) - left6) <= Abs((X - 290) - left7) Then
tx = left6
ElseIf Abs((X - 290) - left7) <= Abs((X - 290) - left8) Then
tx = left7
Else
tx = left8
End If
If (Y - 290) <= top0 Then
ty = top0
ElseIf (Y - 290) >= top9 Then
ty = top9
ElseIf Abs((Y - 290) - top0) <= Abs((Y - 290) - top1) Then
ty = top0
ElseIf Abs((Y - 290) - top1) <= Abs((Y - 290) - top2) Then
ty = top1
ElseIf Abs((Y - 290) - top2) <= Abs((Y - 290) - top3) Then
ty = top2
ElseIf Abs((Y - 290) - top3) <= Abs((Y - 290) - top4) Then
ty = top3
ElseIf Abs((Y - 290) - top4) <= Abs((Y - 290) - top5) Then
ty = top4
ElseIf Abs((Y - 290) - top5) <= Abs((Y - 290) - top6) Then
ty = top5
ElseIf Abs((Y - 290) - top6) <= Abs((Y - 290) - top7) Then
ty = top6
ElseIf Abs((Y - 290) - top7) <= Abs((Y - 290) - top8) Then
ty = top7
ElseIf Abs((Y - 290) - top8) <= Abs((Y - 290) - top9) Then
ty = top8
ElseIf (Y - 290) <= top9 And Y >= (top9 + top8) / 2 Then
ty = top9
End If
Source.Top = ty
Source.Left = tx
senddata ‘write the data into send buffer
AsyncSocket.Send
Beep
label1.Visible = False
End Sub
Private Sub Form_Load()
frmConnect.Show 1 ‘ Load frmConnect form
Me.Show ‘ Load frmChess form
top0 = 200 ‘ Define ranks on board
top1 = 850
top2 = 1450
top3 = 2050
top4 = 2650
top5 = 3370
top6 = 3970
top7 = 4570
top8 = 5170
top9 = 5790
left0 = 110 ‘ Define columns on board
left1 = 830
left2 = 1520
left3 = 2240
left4 = 2960
left5 = 3680
left6 = 4400
left7 = 5120
left8 = 5840
blusol1.Left = left0 ‘ Arrange the initiate positions of the pieces
blusol1.Top = top3
blusol2.Left = left2
blusol2.Top = top3
blusol3.Left = left4
blusol3.Top = top3
blusol4.Left = left6
blusol4.Top = top3
blusol5.Left = left8
blusol5.Top = top3
blushi1.Left = left3
blushi1.Top = top0
blushi2.Left = left5
blushi2.Top = top0
bluxiang1.Left = left2
bluxiang1.Top = top0
bluxiang2.Left = left6
bluxiang2.Top = top0
bluhorse1.Left = left1
bluhorse1.Top = top0
bluhorse2.Left = left7
bluhorse2.Top = top0
bluju1.Left = left0
bluju1.Top = top0
bluju2.Left = left8
bluju2.Top = top0
General.Left = left4
General.Top = top0
redsol1.Left = left0
redsol1.Top = top6
redsol2.Left = left2
redsol2.Top = top6
redsol3.Left = left4
redsol3.Top = top6
redsol4.Left = left6
redsol4.Top = top6
redsol5.Left = left8
redsol5.Top = top6
redshi1.Left = left3
redshi1.Top = top9
redshi2.Left = left5
redshi2.Top = top9
redxiang1.Left = left2
redxiang1.Top = top9
redxiang2.Left = left6
redxiang2.Top = top9
redhorse1.Left = left1
redhorse1.Top = top9
redhorse2.Left = left7
redhorse2.Top = top9
redju1.Left = left0
redju1.Top = top9
redju2.Left = left8
redju2.Top = top9
marshal.Left = left4
marshal.Top = top9
blugun1.Left = left1
blugun1.Top = top2
blugun2.Left = left7
blugun2.Top = top2
redgun1.Left = left1
redgun1.Top = top7
redgun2.Left = left7
redgun2.Top = top7
End Sub
Private Sub Form_Unload(Cancel As Integer) ‘ Close the form
AsyncSocket.Close
End Sub
End Sub
Private Sub mnuAbout_Click()
Dim ksi$, Aboutstr$
Aboutstr$ = "Chinese Chess"
frmAbout.lblABOUTDEM.Caption = Aboutstr$
frmAbout.lblABOUTDEM.FontUnderline = True
ksi$ = "Knowledge " + Chr(169) + "Systems Institute"
frmAbout.lblKsi.Caption = ksi$
frmAbout.Show 0
End Sub
Private Sub Option2_Click()
'Your move the piece first
label1.Visible = True
frame1.Enabled = False
End Sub
Private Sub Option3_Click()
'Other party move the piece first
label1.Visible = False
frame1.Enabled = False
End Sub
Private Sub receivedata() ‘ Receives data from receive buffer and
Dim string1, string2, string3 ‘ assigns them into pieces’ properties
Dim t As String
t = AsyncSocket.ReceiveBuffer
text5.Text = Len(t) ‘ Total data received
blugun1.Visible = Trim(Left(t, 10))‘ First 10 bytes is assigned to
‘ visible property of bluegun1,
‘ the piece blue cannon
t = Mid(t, 11) ‘ Trip off the first 10 bytes from
‘ from string t
blugun1.Left = Trim(Left(t, 10)) ‘ Assigns next 10 bytes to its
‘ Left property
t = Mid(t, 11)
t = Mid(t, 11)
string3 = Trim(Left(t, 10))
Text3.Text = string3
blugun1.Top = string3 ‘ Assigns next 10 bytes to its top
property
. ‘ Here other pieces are gotten
. ‘ assigned values
.
Beep
End Sub
Private Sub senddata() ‘ Write the pieces’ data into send buffer
Dim string1, string2, string3 As String
Dim t As String
'Predefine the length of the strings
string1 = "0123456789"
string2 = "0123456789"
string3 = "0123456789"
LSet string1 = blugun1.Visible
LSet string2 = blugun1.Left
LSet string3 = blugun1.Top
t = t & string1 & string2 & string3 ‘ Concatenates 3 strings into t
LSet string1 = blugun2.Visible
LSet string2 = blugun2.Left
LSet string3 = blugun2.Top
t = t & string1 & string2 & string3
. ‘ Here the strings from other pieces are concatenated into t
.
.
AsyncSocket.SendBuffer = t
End Sub
Private Sub Timer1_Timer()
Timer1.Enabled = False
End Sub
‘ Transfer the handle of socket in frmConnect form into socket
‘ in frmChess form
Private Sub txtSocketHandle_Change()
AsyncSocket.Socket = CLng(txtSocketHandle.Text)
End Sub