#include
#include
#include
using
namespace
std;
//Server side
int
main(int
argc, char
*argv[])
{
//for the server, we only need to specify a port number
if(argc != 2)
{
cerr << "Usage: port"
<< endl;
exit(0);
}
//grab the port number
int
port = atoi(argv[1]);
//buffer to send and receive messages with
char
msg[1500];
//setup a socket and connection tools
sockaddr_in servAddr;
bzero((char*)&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(port);
//open stream oriented socket with internet address
//also keep track of the socket descriptor
int
serverSd = socket(AF_INET, SOCK_STREAM, 0);
if(serverSd < 0)
{
cerr << "Error establishing the server socket"
<< endl;
exit(0);
}
//bind the socket to its local address
int
bindStatus = bind(serverSd, (struct
sockaddr*) &servAddr,
sizeof(servAddr));
if(bindStatus < 0)
{
cerr << "Error binding socket to local address"
<< endl;
exit(0);
}
cout << "Waiting for a client to connect..."
<< endl;
//listen for up to 5 requests at a time
listen(serverSd, 5);
//receive a request from client using accept
//we need a new address to connect with the client
sockaddr_in newSockAddr;
socklen_t newSockAddrSize = sizeof(newSockAddr);
//accept, create a new socket descriptor to
//handle the new connection with client
int
newSd = accept(serverSd, (sockaddr *)&newSockAddr, &newSockAddrSize);
if(newSd < 0)
{
cerr << "Error accepting request from client!"
<< endl;
exit(1);
}
cout << "Connected with client!"
<< endl;
//lets keep track of the session time
struct
timeval start1, end1;
gettimeofday(&start1, NULL);
//also keep track of the amount of data sent as well
int
bytesRead, bytesWritten = 0;
while(1)
{
//receive a message from the client (listen)
cout << "Awaiting client response..."
<< endl;
memset(&msg, 0, sizeof(msg));//clear the buffer
bytesRead += recv(newSd, (char*)&msg, sizeof(msg), 0);
if(!strcmp(msg, "exit"))
{
cout << "Client has quit the session"
<< endl;
break;
}
cout << "Client: "
<< msg << endl;
cout << ">";
string data;
getline(cin, data);
memset(&msg, 0, sizeof(msg)); //clear the buffer
strcpy(msg, data.c_str());
if(data == "exit")
{
//send to the client that server has closed the connection
send(newSd, (char*)&msg, strlen(msg), 0);
break;
}
//send the message to client
bytesWritten += send(newSd, (char*)&msg, strlen(msg), 0);
}
//we need to close the socket descriptors after we're all done
gettimeofday(&end1, NULL);
close(newSd);
close(serverSd);
cout << "********Session********"
<< endl;
cout << "Bytes written: "
<< bytesWritten << " Bytes read: "
<< bytesRead << endl;
cout << "Elapsed time: "
<< (end1.tv_sec - start1.tv_sec)
<< " secs"
<< endl;
cout << "Connection closed..."
<< endl;
return
0;
}
Amaliy qism:
client.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
//Client side
int
main(int
argc, char
*argv[])
{
//we need 2 things: ip address and port number, in that order
if(argc != 3)
{
cerr << "Usage: ip_address port"
<< endl; exit(0);
} //grab the IP address and port number
char
*serverIp = argv[1]; int
port = atoi(argv[2]);
//create a message buffer
char
msg[1500];
//setup a socket and connection tools
struct
hostent* host = gethostbyname(serverIp);
sockaddr_in sendSockAddr;
bzero((char*)&sendSockAddr, sizeof(sendSockAddr));
sendSockAddr.sin_family = AF_INET;
sendSockAddr.sin_addr.s_addr =
inet_addr(inet_ntoa(*(struct
in_addr*)*host->h_addr_list));
sendSockAddr.sin_port = htons(port);
int
clientSd = socket(AF_INET, SOCK_STREAM, 0);
//try to connect...
int
status = connect(clientSd,
(sockaddr*) &sendSockAddr, sizeof(sendSockAddr));
if(status < 0)
{
cout<<"Error connecting to socket!"<
}
cout << "Connected to the server!"
<< endl;
int
bytesRead, bytesWritten = 0;
struct
timeval start1, end1;
gettimeofday(&start1, NULL);
while(1)
{
cout << ">";
string data;
getline(cin, data);
memset(&msg, 0, sizeof(msg));//clear the buffer
strcpy(msg, data.c_str());
if(data == "exit")
{
send(clientSd, (char*)&msg, strlen(msg), 0);
break;
}
bytesWritten += send(clientSd, (char*)&msg, strlen(msg), 0);
cout << "Awaiting server response..."
<< endl;
memset(&msg, 0, sizeof(msg));//clear the buffer
bytesRead += recv(clientSd, (char*)&msg, sizeof(msg), 0);
if(!strcmp(msg, "exit"))
{
cout << "Server has quit the session"
<< endl;
break;
}
cout << "Server: "
<< msg << endl;
}
gettimeofday(&end1, NULL);
close(clientSd);
cout << "********Session********"
<< endl;
cout << "Bytes written: "
<< bytesWritten <<
" Bytes read: "
<< bytesRead << endl;
cout << "Elapsed time: "
<< (end1.tv_sec- start1.tv_sec)
<< " secs"
<< endl;
cout << "Connection closed"
<< endl;
return
0;
}
Natija:
Laboratoriya ishi №24.
Mavzu: Linux yadrosini kompilatsiya qilish.
Ishdan maqsad: Linux operatsion tizimida GDB uskunasi bilan ishlash. Dasturlarni
otladka qilish ko’nikmalariga ega bo’lish
Nazariy qism:
GDB haqida ma’lumot
GDB - bu GNU loyiha tuzatuvchisi hisoblanig, boshqa dastur ishlab turgan vaqtda
uning ichida nimalar bo’layotganini ko’rishga imkon beradi. Yoki dastur buzilib qolgan
paytda und anima yuz berganini aniqlash imkonini beradi.
GDB dastur xatoliklarini u ishlayotgan paytda toppish uchun 4 xil(yoki undan ham
ko’proq) amallarni bajarishi mumkin:
•
Dasturni unga ta’sir qilishi mumkin bo’lgan barcha parametrlar bilan ishga
tushirish.
•
Tegishli shartlarda dasturni to’xtatish.
•
Dastur to’xtagan paytda nima yuz berganini aniqlash.
•
Dasturda to’g’rilashlar kiritish, xatolikni tuzatish natijalarini tahlil qilish va
keyingisiga o’tish.
Yuqoridagi dasturlar bitta kompyuterda GDB (native) sifatida, boshqa mashinada
(masofaviy), yoki simulyatorda ishga tushishi mumkin. GDB mashxur UNIX va
Microsoft Windows variantlarida, shuningdek Mac OS X da ishlashi mumkin.
GDB qaysi tillarni qo’llab quvvatlaydi?
GDB quyidagi dasturlash tillarini qo’llab quvvatlaydi:
•
Ada
•
Assembly
•
C
•
C++
•
D
•
Fortran
•
Go
•
Objective-C
•
OpenCL
•
Modula-2
•
Pascal
•
Rust
broken.cpp
#include
#include
using namespace std;
int ComputeFactorial(int number) {
int fact = 0;
for (int j = 1; j <= number; j++) {
fact = fact * j;
}
return fact;
}
double ComputeSeriesValue(double x, int n) {
double seriesValue = 0.0;
double xpow = 1;
for (int k = 0; k <= n; k++) {
seriesValue += xpow / ComputeFactorial(k);
xpow = xpow * x;
}
return seriesValue;
}
Amaliy qism:
int main() {
cout << "This program is used to compute the value of the following series : " <<
endl;
cout << "(x^0)/0! + (x^1)/1! + (x^2)/2! + (x^3)/3! + (x^4)/4! + ........ + (x^n)/n! " <<
endl;
cout << "Please enter the value of x : " ;
double x;
cin >> x;
int n;
cout << endl << "Please enter an integer value for n : " ;
cin >> n;
cout << endl;
double seriesValue = ComputeSeriesValue(x, n);
cout << "The value of the series for the values entered is "
<< seriesValue << endl;
return 0;
}
Mantiqiy xatolikka ega bo’lgan dasturni tuzatish
Biz ko’rib chiqmoqchi bo’lgan dastur bir nechta mantiqiy xatoliklarga ega. Dastur
kiritilgan x va n uchun (X^0)/0! + (X^1)/1! + (X^2)/2! + (X^3)/3! + (X^4)/4! + ... +
(X^n)/n! ifodasining yig’indisini hisoblab chiqarib beradi. Kiritilgan qiymatlarning
qanday bo’lishidan qat’iy nazar, dastur natijasi cheksizlik (infinity) bo’ladi. Biz tuzatish
jarayonini qadamma qadam olib boramiz va xatoliklarni kuzatamiz:
1.
Yuqoridagi
broken.cpp
nomli faylni ko’chirib oling va shu nom bilan saqlang.
2.
Dasturni kompilyatsiya qilib ishga tushiring.
% g++ -g broken.cpp -o broken
% ./broken
Kiritiluvchi qiymatlar qanday bo’lishidan qat’iy nazar natija inf bo’ladi. Buyruqdagi -g
opsiyasi GDB tuzatish uchun kerak bo’ladi.
3.
Tuzatish dasturini ishga tushiring
% gdb broken
Bu buyruq faqatgina tuzatish dasturini ishga tushiradi, dasturning o’zini emas.
4.
Dastur kodiga qarang va 43-qatorda to’xtash nuqtasi (breakpoint) ni qo’ying.
(gdb) b 43
Quyida dasturning 43-qatori
double seriesValue = ComputeSeriesValue(x, n);
5.
Endi biz tuzatuvchida dasturni ishga tushiramiz.
(gdb) run
Eslatma: Agar dasturni ishga tushirishda qo’shimcha argumentlar bo’lsa ularni oddiy
buyruqlar qatorida yozganingiz kabi run buyrug’idan so’ng berish mumkin.
6.
Dastur ishga tushadi va kiritiluvchi qiymatlarni so’raydi.
Qiymatlarni x=2 va n=3 ko’rinishida berib ko’raylik. Kutilgan natija 5 bo’lishi kerak.
Quyida tuzatuvchida ishlayotgan dastur natijalari:
This program is used to compute the value of the following series :
(x^0)/0! + (x^1)/1! + (x^2)/2! + (x^3)/3! + (x^4)/4! + ........ + (x^n)/n!
Please enter the value of x : 2
Please enter an integer value for n : 3
Breakpoint 1, main () at broken.cpp:43
43 double seriesValue = ComputeSeriesValue(x, n);
Dastur bajarilishi to’xtatish nuqtasida to’xtaganiga e’tibor bering.
7.
ComputeSeriesValue() funksiyasiga qadamlab o’ting
Funksiyaga qadamlab o’tish uchun quyidagi buyruqni ishlatishimiz mumkin:
(gdb) step
ComputeSeriesValue (x=2, n=3) at broken.cpp:17
17 double seriesValue=0.0;
Bu nuqtada dastur nazorati ComputeSeriesValue (x=2, n=3) funksiyasining birinchi
qatorida
8.
Navbatdagi ComputeFactorial gacha qadamlab o’tib boraylik.
9.
(gdb) next
10.
18 double xpow=1;
11.
(gdb) n
12.
20 for (int k = 0; k <= n; k++) {
13.
(gdb)
14.
21 seriesValue += xpow / ComputeFactorial(k) ;
15.
(gdb) s
16.
ComputeFactorial (number=0) at broken.cpp:7
17.
7 int fact=0;
Bu yerda biz next buyrug’ini ishlatamiz. Bu buyruq step ga o’xshab ketadi. Farqli
jihati funksiyani ichiga kirmay o’tadi. Funksiyalar bo’lmagan paytda ikki buyruqning
farqi qolmaydi. GDB buyruqlarini qisqa ko’rinishlaridan ham foydalanishingiz mumkin.
Biz bu yerda next va step o’rniga mos ravishda n va s dan foydalanyapmiz. Agar
bajarmoqchi bo’lgan buyrug’ingiz avvalgisi bilan bir xil bo’lsa, shunchaki Enter
tugmasini bosishingiz kifoya. Va nihoyat, biz ComputeFactorial()funksiyasiga(s bilan)
o’tib boramiz. (Agar biz next ni ishlatganimizda u ComputeFactorial funksiyasiga
kirmasdan o’tib ketgan bo’lar edi.)
18.
Biz qayerdamiz?
Agar dastur bajarilishini qaysi nuqtasida(va qanday qilib bu yerga kelib
qolganingizni) ekanligingizni bilmoqchi bo’lsangiz, backtrace buyrug’i yordamida
quyidagicha stekni ko’rishingiz mumkin:
(gdb) bt
#0 ComputeFactorial (number=0) at broken.cpp:7
#1 0x08048907 in ComputeSeriesValue (x=3, n=2) at broken.cpp:21
#2 0x08048a31 in main () at broken.cpp:43
19.
O’zgarishlarni ko’rish uchun dasturda qadamlab o’tishimiz va print buyrug’I
yordamida o’zgaruvchilar qiymatini chiqarib, tahlil qilishimiz mumkin.
20.
(gdb) n
21.
9 for (int j = 0; j <= number; j++) {
22.
(gdb) n
23.
10 fact = fact * j;
24.
(gdb) n
25.
9 for (int j = 0; j <= number; j++) {
26.
(gdb) print fact
27.
$2 = 0
28.
(gdb) n
29.
13 return fact;
30.
(gdb) quit
Dostları ilə paylaş: |