1
COMP445COMP445Fall 2006Fall 2006
Lab assignment 1
2
STEP1: Get the name of the second party
STEP2: Get phone number from white pages
CALLER RECEIVER
STEP1: Plug the phone, and listen for incoming calls on a certain line
STEP3: Copy the number for your records
STEP4: Call the other party
ConnectionEstablished.
Chat…
STEP2: Get a call and accept it. “Caller ID” will give you the caller’s phone number.
3
Program architectureProgram architecture
ClientServerport 7070
4
Socket Programming
• Berkeley added a new interface to the operating system to support network communication. This interface is generally known as the Berkeley Sockets Interface and is the basis for almost all existing TCP/IP network protocol interfaces, including Windows Sockets
(commonly referred to as WinSock). • A socket is very much like a telephone - it's the endpoint
of a two-way communications channel. By connecting two sockets together you can pass data between
processes running on different computers.
5
Main steps – client sideMain steps – client sideCreating a socket
SOCKET socket(int domain, int type, int protocol);
s = socket(AF_INET,SOCK_STREAM,0)
The structure we fill in is defined below.
struct sockaddr_in { short sin_family; // address family u_short
sin_port;// service port struct in_addr 16 bit TCP or UDP port number, network byte order
sin_addr; // internet address char 32 bits IPv4 address, Network Bytes Order
sin_zero[8]; // filler
}sa_in
6
Main steps – client sideMain steps – client sideClient needs the address of the server.User inputs the server’s hostname.rp=gethostbyname(remotehost)
Fill in the server address memset(&sa_in,0,sizeof(sa_in)); memcpy(&sa_in.sin_addr,rp->h_addr,rp->h_length); sa_in.sin_family = rp->h_addrtype; sa_in.sin_port = htons(port); //port = 7070 host to network 16 bits
Connectingif (connect(s,(LPSOCKADDR)&sa_in,sizeof(sa_in)) == SOCKET_ERROR)
throw "connect failed\n"; Sending frames
ibytessent = send(s, (char*)&message_frame, sizeof(message_frame), 0);
Receiving frames
ibytesrecv = recv(s, (char*)& data_frame, sizeof(data_frame),0)
7
Main steps – server sideMain steps – server side
Creating a socket
s = socket(AF_INET,SOCK_STREAM,0)
Fill in the server port and address info
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
Bind the server port if (bind(s,(LPSOCKADDR)&sa,sizeof(sa)) == SOCKET_ERROR)
Listen for client requests if(listen(s,10) == SOCKET_ERROR)
8
Main steps – server sideMain steps – server sideWatching for new messages
FD_SET(s,&readfds); //always check the listener if(!(outfds=select(infds,&readfds,NULL,NULL,tp))) {} else if (outfds == SOCKET_ERROR)
throw "failure in Select";
else if (FD_ISSET(s,&readfds))
cout << "got a connection request" << endl;
Accept the request
if((s1=accept(s,&ca.generic,&calen))==INVALID_SOCKET) throw "Couldn't accept connection\n";
Read a message
if((ibytesrecv = recv(s1,szbuffer,128,0)) == SOCKET_ERROR)
Send a message
if((ibytessent = send(s1,szbuffer,ibufferlen,0))== SOCKET_ERROR)
9
Socket Functions
• int socket(int family, int type, int protocol);
returns: nonnegative descriptor if OK, -1 on error
• int connect(int sockfd, const struct sockaddr * servaddr, int addrlen);
return:0 if OK -1 on error
• int bind(int sockfd, const struct sockaddr * myaddr, int addrlen);
return: 0 if OK, -1 on error
• int listen(int sockfd, int backlog);
return: 0 of OK, -1 on error
• int accept(int sockfd, struct sockaddr * cliaddr, int * addrlen);
returns: nonnegative descriptor if OK,-1 on error
10
CLIENT SERVERPURPOSE: File Transfer-Get a file-Send a file
•Should inform the server if the required action is to get a file from the server to upload a file to the server.•Should specify the name of theFile.•Respond to possible error messages.
•If a file is asked for, then it shouldsend an error message if file doesn’t exist.•If file exists, send it.•If file is being sent to you, save it.
11
Transferring the data in and Transferring the data in and from the packet structurefrom the packet structure
Struct CONTROL_FRAME {unsigned char direction; //GET or PUTchar fname[MAX]; //filename
}
struct MESSAGE_FRAME {unsigned char header; //ERROR,DATA,LASTPACKET, etc.char data[MAX_SIZE]; //data or error message
} message_frame;
YOU ARE FREE TO DESIGN YOUR OWN STRUCTURES
12
Reading from a fileReading from a filevoid main( void ) {
FILE *stream;
int numread, numwritten;
if( (stream = fopen( "fread.out", "r+b" )) != NULL ) {
…
numread = fread(message_frame.data,sizeof(char), MAX_SIZE, stream);
…}
else
printf( "File could not be opened\n" );
…}
fclose( stream );
}
Be careful if you use strcpy when reading from a binary file use memcpy.
13
Writing in a fileWriting in a filevoid main( void ) {
FILE *stream;
int numread, numwritten;
if( (stream = fopen( "fread.out", "w" )) != NULL ) {
…
numwritten = fwrite(szbuffer, sizeof(char), MAX_SIZE, stream );
…}
else{
printf( "Problem opening the file\n" );
…}
fclose( stream );
}
14
Decrypting the headerDecrypting the headerUse a switch to treat each of the cases:
switch (message_frame.header){
case 1 : …; break;
case 2 : …; break;
case 3 : …; break;
…………………………………………………………………………
default: …
}
15
HintsHints• Use a log file in each side in order to
monitor all the actions:– receiving a packet– sending a packet, etc.
• Open and close the log file after each read/write operation if your program freezes and you cannot read the log file.
• Do not use any string library function! You will be able to send only text files but not binary ones (jpeg or exe for example).
• Instead use memcpy for transferring data.• Do not care about the order of the receiving
packets in this assignment (TCP will do it for you).
16
Assignment 1
• No GUI
• Use Visual C++ 6
• Groups of NOT more than 2• wsock32.lib or you add the following
command to your code:#pragma comment(lib,"wsock32.lib")
• Implement only whatever you’re asked to do.
17
Multi-thread in Windows
uintptr_t _beginthread( void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist );
Parameters:
start_address
Start address of routine that begins execution of new thread.
stack_size
Stack size for new thread or 0.
arglist
Argument list to be passed to new thread or NULL.
18
The C++ Thread Class provided to you#define STKSIZE 16536class Thread{ public:Thread(){}
virtual ~Thread() {}static void * pthread_callback (void * ptrThis);virtual void run () =0 ;void start();
};
void * Thread::pthread_callback (void * ptrThis) { if ( ptrThis == NULL ) return NULL ; Thread * ptr_this =(Thread *)(ptrThis) ; ptr_this->run(); return NULL;} void Thread::start () { int result; if(( result = _beginthread((void (*)(void *))Thread::pthread_callback,STKSIZE,this ))<0)
{printf("_beginthread error\n");exit(-1);
} }
19
How to make _beginthread work in VC6.00++
Right click the project and go to the Setting->C/C++->Category. Change the Category to “Code Generation” and change Use run-time library to “Multithreaded”.Note:You will encounter such a error “error C2065: '_beginthread' : undeclared identifier” at the compile time if you don’t do the above setting.