<![CDATA[Latest posts for the topic "Lập trình socket với *Nix "]]> /hvaonline/posts/list/24.html JForum - http://www.jforum.net Lập trình socket với *Nix 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. ]]>
/hvaonline/posts/list/30602.html#188726 /hvaonline/posts/list/30602.html#188726 GMT
Lập trình socket với *Nix /hvaonline/posts/list/30602.html#265909 /hvaonline/posts/list/30602.html#265909 GMT Lập trình socket với *Nix /hvaonline/posts/list/30602.html#267106 /hvaonline/posts/list/30602.html#267106 GMT