network programmingvishnu/gameprog... · – senddatatest.cpp -> main – socketobject.cpp ->...

40
1 Network programming Socket programming SocketObject class (c++) โครงสรางฝserver โดยคราวๆ SocketObject clientSocketObject, serverSocketObject; serverSocketObject.Bind(6000); serverSocketObject.Listen(); serverSocketObject.Accept(clientSocketObject); serverSocketObject.Disconnect(); จะใช port นีรอ client รับและ accept connection request

Upload: others

Post on 19-May-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

1

Network programming

Socket programming

SocketObject class (c++)• โครงสรางฝง server โดยคราวๆSocketObject clientSocketObject,

serverSocketObject;

serverSocketObject.Bind(6000);serverSocketObject.Listen();serverSocketObject.Accept(clientSocketObject);serverSocketObject.Disconnect();

จะใช port นี้

รอ client

รับและ accept connection request

Page 2: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

2

โครงสรางฝง client

If(clientSocketObject.Connect(“100.100.100.100”, 6000){

…..clientSocketObject.Disconnect();}

ทดลอง ConnectionTest

• มี– Connectiontest.cpp -> main– Socketobject.cpp -> class SocketObject– Socketobject.h -> header– Ws2_32.lib -> windows library for socket– Winsock.h -> header ของตัวขางบน

ตอง link library นี้

Page 3: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

3

1. // Standard Includes2. #include <iostream.h>3. #include

"..\\socketobject\\SocketObject.h"

4. void vServerConnection( int iListenPort );5. void vClientConnection( char

*szServerIP, int iServerListenPort );

แคใหพิมพไปcommand line ได

1. int main( int argc, char *argv[] ){2. //3. // If user selected server, listen on the given port 4. //5. if( !stricmp( argv[1], "server" ) )6. {7. vServerConnection( atoi( argv[2] ) );8. }9. //10. // User selected client, connect to given port and IP

address11. //12. else {13. vClientConnection( argv[2], atoi( argv[3] ) );

14. }15. WSACleanup(); 16. return( 1 );}

จํานวน argument

อารเรยของ argument

รีเทิรน 0 ถาเปนคําเดียวกัน

Page 4: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

4

1. void vServerConnection( int iListenPort )2. {3. SocketObject ServerSocketObject;4. SocketObject ClientSocketObject;5.6. // Attempt to start the server on port 60007. if ( ServerSocketObject.Bind( iListenPort ) )8. {9. // Listen for connection on the Listen port, 10. ServerSocketObject.Listen();

11. // Accept the connection12. ServerSocketObject.Accept( ClientSocketObject

);13. // Disconnect the client14. ClientSocketObject.Disconnect();15. }16. else {}17.}

Disconnect client ออกจาก server (ไมใช disconnect server ออกจาก host)

1. void vClientConnection( char *szServerIP, intiServerListenPort )

2. {3. SocketObject ClientSocketObject;4.5. // Connect to the IP and Port 6. if( ClientSocketObject.Connect( szServerIP,

iServerListenPort ) )7. {8. // Disconnect from the server9. ClientSocketObject.Disconnect();10.11. }12. else {13. cout << "<Client> Failed to Connect" << endl;14. }15. }

Page 5: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

5

การ test ConnectionTest

• ตองrun 2 windows command line เครื่องเราจะเปนทั้ง server และ client– ConnectionTest server 6000 และ– ConnectionTest client 100.100.100.100 6000

– อยาลืมใช cout หรือ print ไมง้ันไมรูวาตอกันติดหรือไมip เราเอง

เขียนโปรแกรมสงขอความ SendDataTest

• ลองสง character array ดู (128 bytes)• มี function

–Send() ซึ่งรีเทิรนจํานวน byte ที่สงไปได–Recv() รอขอมูลเขาทาง connection และเก็บขอมูลใน character buffer รีเทิรนจํานวน byte ที่รับได ถาขอมูลไมครบ ตองเรียก Recv() ไปเรื่อยๆจนไดครบ

Page 6: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

6

ทดลอง SendDataTest

• มี– SendDataTest.cpp -> main– Socketobject.cpp -> class SocketObject– Socketobject.h -> header– Ws2_32.lib -> windows library for socket– Winsock.h -> header ของตัวขางบน

• ตอไปเราดูโคดเฉพาะสวนที่ตางเทานั้น

พวกน้ีเหมือนเดิมหมด

Pointer to a receive bufferของ client

void vServerConnection( int iListenPort ){

SocketObject ServerSocketObject;SocketObject ClientSocketObject;char DataPacket[128]; // Data Packetint iBytesReceived = 0; // # of Bytes

//Received

if ( ServerSocketObject.Bind( iListenPort ) ){

ServerSocketObject.Listen();

ServerSocketObject.Accept( ClientSocketObject );

// Receive DataiBytesReceived =

ClientSocketObject.Recv(DataPacket, 128, 0);

Buffer lengthSocket flagยังไมใช

Page 7: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

7

cout << "<Server> Received " << iBytesReceived << " Bytes" << endl;

cout << "<Server> Data Received = " << DataPacket<< endl;

// Disconnect the clientClientSocketObject.Disconnect();

cout << "<Server> Client Disconnected" << endl;}else {

cout << "<Server> Failed to Listen" << endl;}

}โปรแกรมนี้สมมติวาขอมูลที่สงไมมีการสูญหายหนาตอไปเปน client

void vClientConnection( char *szServerIP, intiServerListenPort )

{SocketObject ClientSocketObject;char DataPacket[128]; // Data Packet to

// Transmitint iBytesSent = 0; // # of Bytes Sent

if( ClientSocketObject.Connect( szServerIP, iServerListenPort ) ){

// Populate the data packetstrcpy(DataPacket, "TestData from Client");

// Send dataiBytesSent = ClientSocketObject.Send(DataPacket,

128, 0);โปรแกรมทํางานตอไดเลย

Page 8: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

8

cout << "<Client> Transmitted " << iBytesSent << " Bytes" << endl;

// Disconnect from the serverClientSocketObject.Disconnect();

cout << "<Client> Disconnected From Server" << endl;}else {

cout << "<Client> Failed to Connect" << endl;}

}

การ test SendDataTest

• เหมือนเดิม ไมพูดแลว

Page 9: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

9

การเขียนโปรแกรม chat

• สง chat ระหวาง client และ server• vGetPacket()

– Get packet ใน retrieve buffer– ทําใหรับขอมูลโดยไมตองรอ ก็คือใชแบบเดียวกับ Recv() แตมันไม

block• _kbhit()

– Check keyboard input โดยไมมีการรอ input

Function นี้มีเฉพาะใน visual c++

Simplechat.cpp#include <iostream.h>#include <stdio.h>#include <conio.h>#include "..\\SocketObject\\SocketObject.h"

struct stChatPacket{

stPacketHeader stHeader;char szChatMessage[128];

};

void vServerConnection( int iListenPort );void vClientConnection( char *szServerIP, int

iServerListenPort );

For console i/o

For printf()

Define ใน SocketObject.h

Page 10: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

10

หนาแทรก stPacketHeader

• int iType - type of the sent packet• int iLength – packet length• int iID – packet ID , เปน 0 ไดถาเราไมตองการ• int iCheckSum - = length + type + ID• int iSender – ID ของ sender

int main( int argc, char *argv[] ){//

// If user selected server, listen on the given port //if( !stricmp( argv[1], "server" ) ){

vServerConnection( atoi( argv[2] ) );}//// User selected client, connect to given port and IP address//else {

vClientConnection( argv[2], atoi( argv[3] ) );}

return( 1 );}

Page 11: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

11

void vServerConnection( int iListenPort ){

SocketObject ServerSocketObject; SocketObject ClientSocketObject;char DataPacket[128]; //Data Packet to transmitint iBytesReceived = 0; // # of Bytes Receivedint iBytesSent = 0; // # of Bytes Sentchar szCommand[128]; // Chat Bufferchar szTempChar;int i;stChatPacket ChatPacket;char szPacketBuffer[32768]; // packet received or send

if ( ServerSocketObject.Bind( iListenPort ) ) {ServerSocketObject.Listen( );ServerSocketObject.Accept( ClientSocketObject );

ตอหนาตอไป

// Loop forever or until a break is issuedwhile( 1 ) {

printf("\n<Server> ");

// Loop through getting up to 127 characters to transmit, leave room //for \n codefor( i = 0; i < 127; i++ ) {

// Loop until a key is pressedwhile( !_kbhit() ) {

// Check for incomming dataiBytesReceived = ClientSocketObject.vGetPacket(szPacketBuffer);if( iBytesReceived > 0 ) {

// Copy the received data into the chat packet

memcpy(&ChatPacket, szPacketBuffer, sizeof(ChatPacket));

strcpy( DataPacket, ChatPacket.szChatMessage);

เหลือ1ที่ให null terminator

ไมตองเช็คtypeเพราะเรามีขอมูลแบบเดียวในตัวอยางนี้

นี่คือสวนของการsend

ในนี้คือสวนการ receive

Page 12: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

12

//continue from strcpy if( !stricmp( DataPacket, "/exit" ) ) {

break;}else {

cout << endl << "<Client> " << DataPacket << endl;

printf("<Server> ");}

} // end if( iBytesReceived..} // end while( !_kbhit()…

// Quit chatting if /exit command givenif( !stricmp( DataPacket, "/exit" ) ) {

break;}

นี่คือ client บอกวาจะออก

// Get next key from keyboard input bufferszTempChar = getche();// Add the keypress to our command stringszCommand[i] = szTempChar;// Check for enter keyif( szTempChar == 13 ) {

break;}

} // end for( i = 0; i < 127;…// Check for user initiated exit codeif( !stricmp( DataPacket, "/exit" ) ) {

break;}// Null Terminate the commandszCommand[i] = '\0';// Populate the packetstrcpy(DataPacket,szCommand);

นี่คือ client บอกวาจะออก

Page 13: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

13

// Quit chatting if /exit command givenif( !stricmp( szCommand, "/exit" ) ) {

break;}else {

// Load the packet dataChatPacket.stHeader.iID = 0;ChatPacket.stHeader.iType = 0;ChatPacket.stHeader.iLength = 128;ChatPacket.stHeader.iSender = 0;

strcpy(ChatPacket.szChatMessage,DataPacket);ChatPacket.stHeader.iCheckSum = 128;// Load the packet buffermemcpy(szPacketBuffer,&ChatPacket,sizeof(stChatPacket));// Send the dataiBytesSent = ClientSocketObject.Send(szPacketBuffer,

sizeof(stPacketHeader)+128,0);

เตรียมขอมูลกอน send

Sending buffer

นี่คือ server บอกวาจะออก

// Check if client has disconnectedif( iBytesSent == -1 ) {

cout << "<Server> Client No Longer Online" << endl;

break;}

} //end else}// end while(1)// Disconnect the clientClientSocketObject.Disconnect();cout << "<Server> Client Disconnected" << endl;

}else {

cout << "<Server> Failed to Listen" << endl;}}// end vserverconnection หนาตอไปเปน client

Page 14: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

14

void vClientConnection( char *szServerIP, int iServerListenPort ){

SocketObject ClientSocketObject; // Client Socket Objectchar DataPacket[128]; // Data Packet to Transmitint iBytesReceived = 0; // # of Bytes Receivedint iBytesSent = 0; // # of Bytes Sentchar szCommand[128]; // Chat Bufferchar szTempChar;int i;char szPacketBuffer[32768];stChatPacket ChatPacket;

// Connect to the IP and Port if( ClientSocketObject.Connect( szServerIP, iServerListenPort ) ) {

// Keep Chatting until a /exit is givenwhile( 1 ) {

printf("\n<Client> ");// Loop through getting up to 127 characters to // transmit, leave room for \n codefor( i = 0; i < 127; i++ ) {

// Loop until a key is pressedwhile( !_kbhit() ) {

// Check for incomming dataiBytesReceived =

ClientSocketObject.vGetPacket(szPacketBuffer);if( iBytesReceived ) {

// Copy the received data into //the chat packet

memcpy(&ChatPacket, szPacketBuffer, sizeof(ChatPacket));

strcpy(DataPacket, ChatPacket.szChatMessage);printf("<Client> ");

}}// Get next key from keyboard input bufferszTempChar = getche();

Page 15: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

15

szTempChar = getche();// Add the keypress to our command stringszCommand[i] = szTempChar;// Check for enter keyif( szTempChar == 13 )

break;} // end for// Null Terminate the commandszCommand[i] = '\0';// Populate the packetstrcpy(DataPacket,szCommand);// Quit chatting if /exit command givenif( !stricmp( szCommand, "/exit" ) ) {

break;}else {

// Load the packet dataChatPacket.stHeader.iID = 0;ChatPacket.stHeader.iType = 0;ChatPacket.stHeader.iLength = 128;

ChatPacket.stHeader.iSender = 0;strcpy(ChatPacket.szChatMessage,DataPacket);ChatPacket.stHeader.iCheckSum = 128;// Load the packet buffermemcpy(szPacketBuffer, &ChatPacket,

sizeof(stChatPacket));// Send the dataiBytesSent =

ClientSocketObject.Send(szPacketBuffer, sizeof(stPacketHeader)+128,0);

// Check if client has disconnectedif( iBytesSent == -1 ) {

cout << "<Server> Client No Longer Online" << endl;

break;}// Check for server disconnectionif( iBytesSent == -1 ) {

cout << "<Client> Server No Longer Online" << endl;

break;}

Page 16: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

16

// Quit chatting if /exit command givenif( !stricmp( szCommand, "/exit" ) ) {

break;}

}} // end while

// Disconnect from the serverClientSocketObject.Disconnect();

cout << "<Client> Disconnected From Server" << endl;}else {

cout << "<Client> Failed to Connect" << endl;}

}

การ test Simplechat

• Simplechat server 6000• Simplechat client 100.100.100.100 6000• Message ยังถูก interrupt ได• Backspace ยังใชไมได

Page 17: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

17

c++ class และ constructor

• กอนอื่นดู c++ class และ constructorClass MonsterObject{

public:int iXPos, iYPos;int iHP; …MonsterObject(); // Constructorint inflictDamage(int damage);

};

MonsterObject::MonsterObject(void){iXPos = iYPos =0;iHP =250;

…}Int MonsterObject :: inflictDamage(int damage){

iHP-=damage}MonsterObject Monsters[100];Void main(void){

…Monsters[id].inflictDamage(…);

}

constructor

method

Page 18: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

18

Socket (ไมใช SocketObject นะ)

• Socket มี 2 ประเภท– Stream

• constant stream, no breakpoint• Data เรียงลําดับอยางแนนอน

– Datagram• สงเปนบล็อก• ไมรับประกันการเรียงของบล็อกตางๆ• ขอมูลสูญหายงาย• แตเร็ว

Socket (ตอ)

class SocketObject {

private:public:

SOCKET skSocket;… เดี๋ยวมีเติม เมธอดตางๆเรื่อยๆ

Page 19: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

19

Bind (prototype)

• int bind(SOCKET s, const struct socaddr FAR* name, int namelen);

struct sockaddr_in{short sin_family; //always AF_INETunsigned short sin_port; //ip port 0 to 10000struct in_addr sin_addr; //ip addresschar sin_zero[8]; //fill space to make

//sockaddr_in as big as //sockaddr (for type casting)

};

Address to store bind information

0 ถา success และ SOCKET_ERROR ถา fail

Length of sockaddr

in_addrStruct in_addr{

union{struct{

unsigned char s_b1,s_b2, s_b3, s_b4;

} S_un_b;struct{

unsigned short s_w1,s_w2;} S_un_w;unsigned long S_addr;

} S_un;};

สวนของ ip address

Page 20: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

20

socket() สราง socket มาใชใน bind

SOCKET socket(int af, int type, int protocol)

AF_INET

SOCK_STREAM หรือ SOCK_DGRAM

เปน 0 ไวกอน

ถา fail จะรีเทิรน INVALID_SOCKET

ภาพรวมการ connect

• Initialize winsock• Create a socket• Bind to server• Listen for connection• Accept client connection

หนาตอไปเปนโคดการ bind (ไมใช class)

Page 21: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

21

#include <iostream.h>#include <winsock.h>#include <stdio.h>

void main(void){

SOCKET skSocket; //socket ที่เราจะสรางsockaddr_in saServerAddress; //socket addressint iPort = 6000, iStatus; // status of WSAStartup()WSADATA wsaData; //info of winsock implementationWORD wVersionRequested; //winsock version

// Tell WinSock we want version 2wVersionRequested = MAKEWORD( 2, 0 );

// Initialize the socket handleskSocket = INVALID_SOCKET;

// Startup WinSockiStatus = WSAStartup( wVersionRequested, &wsaData );

ไมตองสน เดี๋ยวมันทําเอง

// Create the socketskSocket = socket( AF_INET, SOCK_STREAM, 0 );

// Check if there was an errorif( skSocket == INVALID_SOCKET ) {

cout << "**ERROR** Could Not Create Socket" << endl;// Clean up WinSockWSACleanup();exit(1);

}

cout << "<-- SOCKET CREATED -->" << endl;

// Clear out the socket address structure ใหขอมูลทุกตัวเปน 0memset(&saServerAddress, 0, sizeof(sockaddr_in));

// Initialize the socket address structuresaServerAddress.sin_family = AF_INET;saServerAddress.sin_addr.s_addr = htonl( INADDR_ANY );saServerAddress.sin_port = htons( iPort );

Convert u_long to byte order used by TCP/IP

Convert u_short to byte order used by TCP/IP

Page 22: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

22

// Attemp to bindif( bind( skSocket, (sockaddr*) &saServerAddress, sizeof(sockaddr) ) == SOCKET_ERROR ) {

cout << "**ERROR** Could Not Bind" << endl;// Clean up WinSockWSACleanup();exit(1);

}

// Close the socket and return resource to the systemclosesocket(skSocket);

// Clean up WinSockWSACleanup();

cout << "<-- SOCKET BOUND -->" << endl;}

การ bind ในคลาส

• ส่ิงที่ bind ตองการใชคือ socket handle กบั port number

• เราสราง socket handle เองอยูแลว ก็เลยเหลือ port number เทานั้น

• ดูโคดในหนาถัดไป

Page 23: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

23

int SocketObject::Bind(int iPort){

sockaddr_in saServerAddress;skSocket = socket(AF_INET, SOCK_STREAM, 0);if(skSocket == INVALID_SOCKET){

return false;}memset(&saServerAddress, 0, sizeof(sockaddr_in));saServerAddress.sin_family = AF_INET;saServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);saServerAddress.sin_port = htons(iPort);

if( bind(skSocket, (sockaddr*) &saServerAddress, sizeof(sockaddr)) == SOCKET_ERROR){

Disconnect();return false;

} elsereturn true;

}

ไมมีการ initialize หรือ clean up winsock เพราะทาํโดย constructor และ destructor

Constructor/destructor// ConstructorSocketObject::SocketObject(){

WSADATA wsaData;WORD wVersionRequested;

wVersionRequested = MAKEWORD( 2, 0 );

skSocket = INVALID_SOCKET;iStatus = WSAStartup(wVersionRequested,&wsaData);

}

// DestructorSocketObject::~SocketObject(){

Disconnect();}

Page 24: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

24

Disconnect()

void SocketObject::Disconnect(){

if(skSocket != INVALID_SOCKET){

closesocket(skSocket);skSocket = INVALID_SOCKET;

}} ไมทํา WSACleanup() เพราะไมง้ันจะ unload บอยไป

ปลอยใหโปรแกรมเมอรเรียกใชเองดีกวา

ทบทวนการใชงาน SocketObject.bind()#include <iostream.h>#include "..\\socketobject\\SocketObject.h"void main( void ){

SocketObject ServerSocketObject;int iPort = 6000;

// Attempt to bindif ( ServerSocketObject.Bind( iPort ) ) {

cout << "<-- SOCKET BOUND -->" << endl;ServerSocketObject.Disconnect();

}else {

cout << "**ERROR** Could Not Bind" << endl;}WSACleanup();

}

Page 25: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

25

การ listen ธรรมดา • ถาเปนโคดที่ไมใชคลาส เราทําตอจากการ bind ไดทันที โดย c++ จะมี

ฟงกช่ัน listen อยูแลว// Listen for a connectioniStatus = listen( skSocket, 32 );

if( iStatus == SOCKET_ERROR ) {cout << "**ERROR** Error Listening" << endl;// Close the socketclosesocket(skSocket);// Clean up WinSockWSACleanup();exit(1);

}

cout << "<-- SOCKET LISTENING -->" << endl;

Handle ของ socket ของเราจํานวน pending connection ที่เราอนุญาต

ถาปกติจะรีเทิรน 0

การ listen ในคลาส

int SocketObject::Listen( void ){

return listen( skSocket, 32 );}

Page 26: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

26

ทบทวนการใชงานSocketObject.listen()#include ……….

void main( void ){ SocketObject ServerSocketObject;

int iPort = 6000;// Attempt to bindif ( ServerSocketObject.Bind( iPort ) ) {

cout << "<-- SOCKET BOUND -->" << endl;if( ServerSocketObject.Listen() != SOCKET_ERROR ) {

cout << "<-- SOCKET LISTENING -->" << endl;} else {

cout << "**ERROR** Could Not Listen" << endl;}ServerSocketObject.Disconnect();

} else {cout << "**ERROR** Could Not Bind" << endl;

}WSACleanup();

}

การ accept (ใชกับ stream เทานั้น)

accept( skSocket, (struct sockaddr*)& saClientAddress, &iClientSize );

Handle to server socket to accept, must be in listening state, type:SOCKET

Client IP อยูในนี้ ,type: struct sockaddr FAR*

ขนาดของ parameter ตัวที่สอง, type:int FAR*

รีเทิรน socket handle หรือ INVALID_SOCKET

Page 27: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

27

การ accept เมือ่ไมมีคลาส• มีตัวแปรเพิ่มนิดหนอย สวนโคดก็จะตอจากการ listen

SOCKET skClientSocket;sockaddr_in saClientAddress;int iClientSize = sizeof(sockaddr_in);…….cout << "<-- SOCKET LISTENING -->" << endl;

skClientSocket = accept( skSocket, (struct sockaddr*)&saClientAddress, &iClientSize );if( skClientSocket == INVALID_SOCKET ) {

cout << "**ERROR** Error Accepting" << endl;closesocket(skSocket);WSACleanup();exit(1);

}

cout << "<-- CLIENT ACCEPTED -->" << endl;

ตัว socket ของ client

การ accept เมือ่ไมมีคลาส (ตอ)// Close the socketsclosesocket(skSocket);closesocket(skClientSocket);

// Clean up WinSockWSACleanup();

}

Page 28: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

28

การ accept ในคลาสbool SocketObject::Accept( SocketObject &skAcceptSocket ){

sockaddr_in saClientAddress;int iClientSize = sizeof(sockaddr_in);

skAcceptSocket.skSocket = accept( skSocket, (structsockaddr*)&saClientAddress, &iClientSize );

if( skAcceptSocket.skSocket == INVALID_SOCKET ) {

return false;} else{

return true;}

}

รับ SocketObject

ทบทวนการใชงาน SocketObject.Accept()void main( void ){ SocketObject ServerSocketObject;

SocketObject ClientSocketObject;int iPort = 6000;if ( ServerSocketObject.Bind( iPort ) ) {

cout << "<-- SOCKET BOUND -->" << endl;if( ServerSocketObject.Listen() != SOCKET_ERROR ) {

cout << "<-- SOCKET LISTENING -->" << endl;if( ServerSocketObject.Accept( ClientSocketObject ) ) {

cout << "<-- CLIENT ACCEPTED -->" << endl;}else { cout << "**ERROR** Could Not Accept" << endl;}

} else {cout << "**ERROR** Could Not Listen" << endl;

}

Page 29: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

29

การใชงาน SocketObject.Accept()(ตอ)ServerSocketObject.Disconnect();} else {

cout << "**ERROR** Could Not Bind" << endl;}WSACleanup();

}

การ connect

• Client เปนคนใชเทานัน้• ตอง

– Initialize winsock– Create a socket

• Connect function มีใน winsock– int connect(SOCKET s, const struct sockaddr

FAR* name, int namelen)

0 ถาทุกอยาง okServer to connect

Size of server address

Socket ที่สรางใหม

Page 30: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

30

การ connect เมื่อไมใชคลาสvoid main(void){

…LPHOSTENT lpHost; // host’s official namechar szHost[128]; //name of server we want to

//connectsprintf(szhost,”192.168.0.2”);…// Initialize the server address data structurememset(&saServerAddress,0,sizeof(sockaddr_in));// Set this by defaultsaServerAddress.sin_family = AF_INET;// Load the IP AddresssaServerAddress.sin_addr.s_addr = inet_addr(szHost);

ดูแผนแทรก

ดูแผนแทรก

Struct hostent{char FAR *h_name;char FAR *FAR *h_aliases;short h_addrtype;short h_length;char FAR *FAR *h_addr_list;

};

Page 31: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

31

• Unsigned long inet_addr(const char FAR *cp)

String containing ip address in dot format

Binary equivalent of the address, or INADDR_NONE

// If the host specified is not an IP Address we must look up the valueif( saServerAddress.sin_addr.s_addr == INADDR_NONE ){

cout << "<-- LOOKING UP HOST IP -->" << endl;// Get the host namelpHost = gethostbyname(szHost);// Check if we got something backif (lpHost != NULL) {

// Load the server address with the host informationsaServerAddress.sin_addr.s_addr = ((LPIN_ADDR)lpHost-

>h_addr)->s_addr;}else {

cout << "**ERROR** Could Not Locate Host" << endl;// Clean up WinSockWSACleanup();exit(1);

}}

เปลี่ยนชื่อ yahoo.com เปน format ของเรา

Page 32: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

32

// Set the Server PortsaServerAddress.sin_port = htons(iPort);

// Attempt to connect to the serveriStatus = connect(skSocket, (structsockaddr*)&saServerAddress,sizeof(sockaddr));

// Check if there was an errorif( iStatus == SOCKET_ERROR ) {

cout << "**ERROR** Could Not Connect To Server" << endl;// Clean up WinSockWSACleanup();exit(1);

}cout << "<-- CONNECTED TO SERVER -->" << endl;// Close the socketclosesocket(skSocket);// Clean up WinSockWSACleanup();

}

Connect ในคลาสbool SocketObject::Connect(char* szServerAddress, int

iPort){

struct sockaddr_in serv_addr;LPHOSTENT lphost;

memset(&serv_addr,0,sizeof(sockaddr_in));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(szServerAddress);

Server address you want to connectPort number of the server

Page 33: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

33

if (serv_addr.sin_addr.s_addr == INADDR_NONE){

lphost = gethostbyname(szServerAddress);if (lphost != NULL)

serv_addr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;

else{

WSASetLastError(WSAEINVAL);return FALSE;

}}

serv_addr.sin_port = htons(iPort);

// Open the socketskSocket = socket(AF_INET, SOCK_STREAM, 0);if(skSocket == INVALID_SOCKET){

return false;}

int err = connect(skSocket, (structsockaddr*)&serv_addr,sizeof(sockaddr));if(err == SOCKET_ERROR){

Disconnect();return false;

}

return true;}

Page 34: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

34

ทบทวน SocketObject.Connect()#include <iostream.h>#include "..\\socketobject\\SocketObject.h"void main( void ){

SocketObject ClientSocketObject;int iPort = 80; // HTTP Portcout << "<-- ATTEMPTING CONNECTION -->" << endl;

// Attempt to connectif ( ClientSocketObject.Connect( "www.lostlogic.com", iPort ) ) {

cout << "<-- SOCKET CONNECTED -->" << endl;}else {

cout << "**ERROR** Could Not Connect" << endl;}WSACleanup();

}

Send

• ใช send() function –winsock• ในโคดที่ไมใชคลาสก็เขียนตอจาก connect ไดเลย

char szSendBuffer[256]; //data we want to sendint iBytesSent; //how many bytes we successfully sent…cout << "<-- CONNECTED TO SERVER -->" << endl;

sprintf(szSendBuffer,"Test Data"); //put “Test Data” in bufferiBytesSent = send(skSocket,szSendBuffer,256,0);

cout << "<-- SENT " << iBytesSent << " BYTES -->" << endl;

Page 35: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

35

send()• int send(SOCKET, const char FAR *buf, int len, int flags);

Socket ที่เราสงขอมูลออก

Character buffer ขอมูลที่ตองการสง

Amount to transmit

Not use

Send() ในคลาส

int SocketObject::Send(char *szBuffer, int iBufLen, int iFlags)

{return send(skSocket,szBuffer,iBufLen,iFlags);

}

Parameter เหมือนเดิมเพียงแตไมมีsocket

Page 36: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

36

การใชงาน Send()#include <iostream.h>#include "..\\socketobject\\SocketObject.h"void main( void ){

SocketObject ClientSocketObject;int iPort = 80; // HTTP Portchar szSendBuffer[256];int iBytesSent;

// Attempt to connectif ( ClientSocketObject.Connect( "www.lostlogic.com", iPort ) ) {

cout << "<-- SOCKET CONNECTED -->" << endl;

sprintf(szSendBuffer,"TEST DATA");iBytesSent = ClientSocketObject.Send(szSendBuffer,256,0);cout << "<-- SENT " << iBytesSent << " BYTES -->" << endl;

}

else {cout << "**ERROR** Could Not Connect" << endl;

}WSACleanup();

}

Page 37: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

37

Receive

• ใช recv() function –winsock• ฟงกช่ันนี้รอจนกวาจะได data• int recv(SOCKET, const char FAR *buf, int len, int flags);

Socket ที่รอขอมูลมา

Character buffer ที่เอาไวรับขอมูลพอรับมาแลวเราคอยเอาใสโครงสรางขอมูลที่ตองการ

ขนาดของขอมูลที่จะรับหามใหญกวาตัว buffer

MSG_PEEKMGG_OOB

Receive (ตอ)• ในโคดที่ไมใชคลาสก็เขียนตอจาก connect ไดเลย อยาลืมวานี่คือ client

char szRecvBuffer[32768];int iBytesReceived;…cout << "<-- CONNECTED TO SERVER -->" << endl;// Load the data to sendsprintf(szSendBuffer,"GET / HTTP/1.0\n\n");// Send the HTTP RequestiBytesSent = send(skSocket,szSendBuffer,256,0);

cout << "<-- SENT " << iBytesSent << " BYTES -->" << endl;

// Wait for incoming dataiBytesReceived = recv(skSocket,szRecvBuffer,32768,0);

// Output the data receivedcout << szRecvBuffer << endl;

ขอ source ของเว็บ

พิมพ source ของเว็บ

Send request

รอคําตอบ

Page 38: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

38

Receive ในคลาส

int SocketObject::Recv( char *szBuffer, int iBufLen, int iFlags)

{return recv(skSocket, szBuffer, iBufLen, iFlags);

}

การใชงาน Receivevoid main( void ){

SocketObject ClientSocketObject;int iPort = 80; // HTTP Portchar szSendBuffer[256];int iBytesSent;char szRecvBuffer[32768];int iBytesReceived;

cout << "<-- ATTEMPTING CONNECTION -->" << endl;

// Attempt to connectif ( ClientSocketObject.Connect( "www.lostlogic.com", iPort ) ) {

cout << "<-- SOCKET CONNECTED -->" << endl;

Page 39: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

39

// Load the request buffersprintf(szSendBuffer,"GET / HTTP/1.0\n\n");// Send the requestiBytesSent = ClientSocketObject.Send(szSendBuffer,256,0);cout << "<-- SENT " << iBytesSent << " BYTES -->" << endl;

// Receive the responseiBytesReceived =

ClientSocketObject.Recv(szRecvBuffer,32768,0);cout << "<-- RECEIVED " << iBytesReceived << " BYTES -->"

<< endl;// Output what was receivedcout << szRecvBuffer << endl;

}else {

cout << "**ERROR** Could Not Connect" << endl;}WSACleanup();

}

ถารับไมครบใหลูปรับขอมูลเรื่อยๆ

SocketObject.h#ifndef SOCKET_OBJECT

#define SOCKET_OBJECT

// Windows Sockets Include, Also need ws2_32.lib included in project#include <winsock.h>#include <stdio.h>

// Class Objectclass SocketObject {

private:

Page 40: Network programmingvishnu/gameProg... · – SendDataTest.cpp -> main – Socketobject.cpp -> class SocketObject – Socketobject.h -> header – Ws2_32.lib -> windows library for

40

public:SOCKETskSocket;intiStatus;

// ConstructorSocketObject();// Desctrucot~SocketObject();

// Accept a client's request to connectbool Accept(SocketObject& skAcceptSocket);// Listen for clients to connect toint Listen(void);// Open a server listening portint Bind(int iPort);// Close connectionvoid Disconnect();

// Connect to a serverbool Connect(char* szServerAddress, int iPort);

int Recv(char *szBuffer, int iBufLen, int iFlags);int Send(char *szBuffer, int iBufLen, int iFlags);

};

#endif