Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
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
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 นี้
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 ถาเปนคําเดียวกัน
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. }
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() ไปเรื่อยๆจนไดครบ
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ยังไมใช
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);โปรแกรมทํางานตอไดเลย
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
• เหมือนเดิม ไมพูดแลว
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
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 );}
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
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 บอกวาจะออก
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
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();
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;}
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 ยังใชไมได
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
18
Socket (ไมใช SocketObject นะ)
• Socket มี 2 ประเภท– Stream
• constant stream, no breakpoint• Data เรียงลําดับอยางแนนอน
– Datagram• สงเปนบล็อก• ไมรับประกันการเรียงของบล็อกตางๆ• ขอมูลสูญหายงาย• แตเร็ว
Socket (ตอ)
class SocketObject {
private:public:
SOCKET skSocket;… เดี๋ยวมีเติม เมธอดตางๆเรื่อยๆ
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
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)
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
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 เทานั้น
• ดูโคดในหนาถัดไป
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();}
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();
}
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 );}
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
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();
}
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;
}
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 ที่สรางใหม
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;
};
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 ของเรา
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
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;}
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;
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
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();
}
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
รอคําตอบ
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;
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:
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