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




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.
























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.











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

      1. Windows Socket API and MFC CAsyncSocket Class 23
      1. Windows Socket API 23
      2. MFC CASyncSocket Class 25

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


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.

  1. TCP/IP Layering

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

  1. Transmit the data on a physical medium

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 "". The other is IP address, such as "". 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, 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.

  1. The server TCP sends a Final Segment(FIN), informing the partner that no

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.

  1. The client application tells its TCP to close.
  2. The client TCP sends a FIN message.

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 (

Local port (10000)

Protocol (TCP or UDP)

Remote IP address (

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.

  1. Specifies the IP address and service port number of the server program, sometimes you need to specify the client's local address and port number and call bind() to copy them into socket address structure.

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 =



In response to the event flag , the class has a set of methods to handle the events.

CAsyncSocket Method Event flag

OnReceive FD_READ


OnOutOfBandData FD_OOB




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 )

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


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 .

  1. Form_Load Sub(): This procedure sets up 10 by 9 points on the chess board,10 points in Y axis and 9 points in X axis. The purpose of this setting is to restrict the locations of the pieces. No matter how you move the pieces, they will fall on these 90 points.
  2. This procedure also set up the initial position of 32 pieces.

  3. Form_DragDrop(): This procedure is defined so that if you drop the piece not exactly at the points defined as above, it will force the piece fall on the nearest point defined.
  4. 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.

  5. What will happen if a piece is eaten or captured?

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




label1.Visible = False

End If

  1. Analysis of The Communication Code

The communication ability is the most important feature of this application. This feature is "played" by ASocket custom control.

  1. Establishing The Connection

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.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



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


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)) = 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.






  1. TCP/IP, Sidnie Feit, 1996 McGraw-Hill, ISBN 0-07-021389-5
  2. Win32 Network Programming, Ralph Davis, 1996 A-W Developers Press,
  3. ISBN 0-201-48930-9

  4. ASocket Document, 1997 Mabry Software
  5. Windows NT Network Programming, Ralph, Davis, 1994

Addison-Wesley Publishing Company, ISBN 0-201-62278-5

  1. Teach Yourself Visual Basic 4 in 21 Days, 3rd Edition, Nathan Gurewich & Ori Gurewich,

1995 SAM Publishing, ISBN 0-672-30620-4

  1. Microsoft C++ 4.0 online references:

"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



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.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


Begin VB.Menu mnuHelp

Caption = "&Help"

Begin VB.Menu mnuAbout

Caption = "About..."




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


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


‘ Socket get the data in send buffer.



‘ 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 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


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



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


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


. ‘ Here other pieces are gotten

. ‘ assigned values



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