[Programming] Lập trình socket với *Nix |
05/08/2009 09:15:52 (+0700) | #1 | 188726 |
|
H3x4
Member
|
0 |
|
|
Joined: 02/04/2009 00:03:16
Messages: 242
Offline
|
|
Tớ xin chia sẻ chút ít kiến thức về lập trình socket trên *Nix, để đọc bài viết này một số kiến thức về network và socket được yêu cầu, bài viết với mục đích chia sẻ cho các bạn muốn bắt đầu học lập trình mạng bằng C nhưng chưa biết bắt đầu ra sao. Hi vọng sẽ giúp được phần nào cho mọi người.
Để demo cho bài viết xin được lấy ví dụ là wargame level1 của vortex.
Đầu tiên các bạn cần có một bảng tra cứu các system call về network trên Linux.
Có 1 cái cơ bản ở đây và từ đó các bạn có thể tra cứu ra các system call khác :
http://isomerica.net/~dpn/socketcall1.pdf
Chúng ta bắt đầu : Đọc đề !
Your goal is to connect to port 5842 on vortex.labs.pulltheplug.org and read in 4 unsigned integers. Add these integers together and send back the results to get a username and password for level 1.
Chúng ta xác định bước đầu tiên khi muốn connect tới một địa chỉ trên mạng là phải tạo ra 1 socket và từ socket này mới có thể trao đổi dữ liệu được. Chúng ta sẽ tham khảo manpage cho lệnh tạo socket :
http://www.manpagez.com/man/2/socket/
Tất nhiên chúng ta chỉ việc gõ vào console : man socket là sẽ có cái này, ở đây mình chỉ muốn đưa cho các bạn thấy trực tiếp mà không cần phải vào terminal. Chúng ta sẽ chú ý đến những điểm chính sau:
Code:
#include <sys/types.h>
#include <sys/socket.h>
int
socket(int domain, int type, int protocol);
The domain parameter specifies a communications domain within which com-
munication will take place; this selects the protocol family which should
be used. These families are defined in the include file <sys/socket.h>.
The currently understood formats are
AF_UNIX (UNIX internal protocols),
AF_INET (ARPA Internet protocols),
AF_ISO (ISO protocols),
AF_NS (Xerox Network Systems protocols), and
AF_IMPLINK (IMP host at IMP link layer).
The socket has the indicated type, which specifies the semantics of com-
munication. Currently defined types are:
SOCK_STREAM
SOCK_DGRAM
SOCK_RAW
SOCK_SEQPACKET
SOCK_RDM
Như vậy chương trình của chúng ta sẽ bắt đầu như sau:
Code:
#include <stdio.h>
#include <sys/types.h>
int main(int argc, chả **argv)
{
int sockfd;
sockfd = socket ( AF_INET, SOCK_STREAM,0); // chúng ta dùng AF_INET và SOCK_STREAM để tạo socket dùng cho mạng internet và theo giao thức TCP.
}
Từ manpage này mà ta có các system call khác để có thể tham khảo :
accept(2), bind(2), connect(2), getsockname(2), getsockopt(2), ioctl(2),
listen(2), read(2), recv(2), select(2), send(2), shutdown(2),
socketpair(2), write(2), getprotoent(3), inet(4), inet6(4), unix(4),
compat(5)
Sau khi tạo ra socket chúng ta cần connect nó tới đích. CHúng ta thấy ở trên có system call là connect chúng ta sẽ coi manpage của nó :
http://www.manpagez.com/man/2/connect/
Và cũng chú ý một số điểm sau:
Code:
int
connect(int socket, const struct sockaddr *address,
socklen_t address_len);
Thông thường chúng ta sẽ dùng sockaddr_in cho địa chỉ của host cần connect tới.
Google một chút là ta có trang này để tham khảo :
http://www.csc.villanova.edu/~mdamian/Sockets/TcpSockets.htm
Chúng ta sẽ thêm vào chương trình của mình như sau:
Code:
#include <stdio.h>
#include <sys/types.h>
int main(int argc, chả **argv)
{
if(argc != 3)
{
fprintf(stderr, "usage: %s hostname portno \n", argv[0]);
return 1;
}
//Dùng để yêu cầu user nhập vào hostname và port
int sockfd,portno;
portno = atoi(argv[2]);
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons (portno);
sockfd = socket ( AF_INET, SOCK_STREAM,0);
// chúng ta dùng AF_INET và SOCK_STREAM để tạo socket dùng cho mạng internet và theo giao thức TCP.
if(connect (sockfd, &server_addr, sizeof(server_addr)) == 0)
{
perror("Socket connection");
}
}
Tạm thời chúng ta chưa có struct in_addr sin_addr. Chúng ta chỉ có địa chỉ website là :vortex.labs.pulltheplug.org.
Chúng ta sẽ chuyển qua một system call là gethostbyname : nó sẽ trả về cho chúng ta địa chỉ IP của một domain. Xem xét manpage của nó :
[url]
http://www.manpagez.com/man/3/gethostbyname/[/url]
Để phục vụ cho mục đích lấy IP chúng ta cần một cấu trúc mới là hostent bởi vì system call gethostbyname sẽ nhận vào url và trả ra một cấu trúc hostent trong đó có cái chúng ta cần là IP address.
Google ta tìm được một ví dụ về gethostbyname :
http://www.logix.cz/michal/devel/various/gethostbyname.c.xp
Ứng dụng vào đoạn code của chúng ta sẽ có được :
Code:
......
struct hostent *he;
struct in_addr addr;
he = gethostbyname ( argv[1]);
bcopy( *he->h_addr_list ,(char *) &addr, sizeof(addr));
Bây giờ thì đã có IP của host , ta sẽ làm đầy cấu trúc sockaddr_in:
Code:
server_addr.sin_addr = addr;
Sau khi đã connect xong chúng ta sẽ nhận dữ liệu từ host bằng lệnh recv. Tiếp tục manpage :
http://www.manpagez.com/man/2/recv/
Ta lại có :
Code:
unsigned int a ;
int sum = 0;
int i = 0;
while ( i < 4)
{
recv( sockfd, (unsigned int) &a,sizeof(unsigned int),0 );
printf("%i\n",a);
sum += a;
i++;
}
printf ("Sum is : %i\n",sum);
Và send ngược lại kết quả cho host :
http://www.manpagez.com/man/2/send/
Code:
send (sockfd, &sum , sizeof(int),0);
Và nhận về kết quả :
Code:
char account[128];
recv(sockfd,account,128,0);
printf("%s",account);
Với bấy nhiêu đó các bạn đã có một chương trình để hoàn thành yêu cầu của đề :
Code:
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
struct sockaddr_in server_addr;
struct hostent *he;
int main(int argc, char **argv)
{
if(argc != 3)
{
fprintf(stderr, "usage: %s hostname portno \n", argv[0]);
return 1;
}
struct in_addr addr;
int sockfd,portno;
unsigned int a;
he = gethostbyname ( argv[1]);
portno = atoi(argv[2]);
bcopy( *he->h_addr_list ,(char *) &addr, sizeof(addr));
printf("address: %s\n", inet_ntoa(addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons (portno);
server_addr.sin_addr = addr;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(connect (sockfd, &server_addr, sizeof(server_addr)) == 0)
{
perror("Socket connection");
}
int sum = 0;
int i = 0;
while ( i < 4)
{
recv( sockfd, (unsigned int) &a,sizeof(unsigned int),0 );
printf("%i\n",a);
sum += a;
i++;
}
printf ("Sum is : %i\n",sum);
send (sockfd, &sum , sizeof(int),0);
char account[128];
recv(sockfd,account,128,0);
printf("%s",account);
}
và :
$gcc -o level0 level0.c
$./level0 vortex.labs.pulltheplug.org 5842
Bingo ! chúng ta có account cho level1 với một chút ít kiến thức về mạng và dựa vào tra cứu tự tìm tòi là chính. Cám ơn các bạn đã đọc bài. Hi vọng nhận được sự góp ý từ mọi người.
|
|
|
|
|
[Programming] Lập trình socket với *Nix |
01/07/2012 22:12:55 (+0700) | #2 | 265909 |
fcbacktrack
Member
|
0 |
|
|
Joined: 29/06/2012 23:30:57
Messages: 38
Offline
|
|
bài anh viết hay lắm rất kỹ đúng là thứ em cần mà cho em hỏi :
perror là gì vậy anh |
|
|
[Programming] Lập trình socket với *Nix |
19/07/2012 15:22:53 (+0700) | #3 | 267106 |
Users currently in here |
1 Anonymous
|
|
Powered by JForum - Extended by HVAOnline
hvaonline.net | hvaforum.net | hvazone.net | hvanews.net | vnhacker.org
1999 - 2013 ©
v2012|0504|218|
|
|