Từ 1 tới 6 trên tổng số 6 kết quả

Đề tài: Lập trình mạng trong Visual C++ 6, xây dựng ứng dụng client server đơn giản

  1. #1
    Ngày gia nhập
    07 2006
    Nơi ở
    Hà nội
    Bài viết
    204

    Mặc định Lập trình mạng trong Visual C++ 6, xây dựng ứng dụng client server đơn giản

    Bài này sẽ hướng dẫn các bạn làm 1 ứng dụng client-server cơ bản.

    I. Socket
    Cơ bản nhất khi lập trình mạng chính là khái niệm socket.
    Socket nghĩa là 1 cái "ổ cắm". Có thể tưởng tượng thế này (xin lỗi vì vẽ hơi xấu ^_^):
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		socket.jpg
Lần xem:	8
Size:		9.7 KB
ID:		8154

    Tất nhiên đường dây ở trên chỉ là đường dây ảo.
    Toàn bộ quá trình trao đổi sẽ diễn ra qua các socket.
    1 socket khi được tạo có thể có các trạng thái: bind (gắn vào 1 cổng), listen (chờ kết nối), connected (đã kết nối với socket khác).
    Socket khi chỉ bind vào 1 cổng có thể nhận các tin được gửi từ mạng đến cổng đó.

    Để tạo 1 socket ta dùng hàm sau:

    SOCKET sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

    - Tham số thứ nhất là loại kết nối, thường là AF_INET.
    - Tham số thứ 2 là kiểu kết nối, SOCK_STREAM cho TCP, SOCK_DGRAM cho UDP và các kiểu connectionless (không cần kết nối).
    - Tham số thứ 3 là giao thức, IPPROTO_TCP chỉ dùng cho SOCK_STREAM.
    (Để biết thêm về các loại giao thức và kết nối, vào MSDN, ở đây chỉ giải thích qua).

    *Chú ý: Ta cần thêm thư viện ws2_32.lib và include file winsock2.h. Để dùng các hàm winsock, trước tiên cần làm thế này:

    Visual C++ Code:
    1. WSADATA wsadata;
    2. WSAStartup (&wsadata, MAKEWORD (2, 2));

    Hàm API WSAStartup sẽ khởi tạo winsock cho ứng dung với phiên bản yêu cầu, ở đây là 2.2, các thống số về winsock sẽ tra lại trong wsadata


    II. Khởi tạo phía server

    Các bước thực hiện trên server:

    B1: Tạo socket TCP.

    Visual C++ Code:
    1. SOCKET ListenSock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

    B2: Bind (gắn) socket này vào 1 cổng, client sẽ nối đến server qua cổng này.

    Ở đây dùng cổng 4444:
    Visual C++ Code:
    1. sockaddr_in name;
    2. name.sin_family = AF_INET;
    3. name.sin_addr.s_addr = inet_addr("127.0.0.1");
    4. name.sin_port = htons(4444);
    5. bind (ListenSock, (sockaddr*) &name, sizeof (name));

    127.0.0.1 là địa chỉ IP quy định đặt cho localhost, cũng có thể dùng địa chỉ ip trong mạng lan như 10.0.0.1....
    Hàm inet_addr ("x.x.x.x") chuyển chuỗi địa chỉ ip thành 1 số 4 byte. Và ngược lại là hàm inet_ntoa (long x), chuyển địa chỉ dạng số 4 byte sang chuổi.

    B3: Cho socket này listen, chờ kết nối.
    Visual C++ Code:
    1. listen (ListenSock, 1);

    Tham số thứ 2 của hàm API listen là backlog, em cũng ko hiểu rõ, nhưng thường được để là 1. Hàm listen là 1 vòng lặp, sẽ kết thúc nếu có 1 yêu cầu kết nối.

    B4: Có yêu cầu kết nối. Nếu đồng ý, sẽ có 1 socket khác được tạo và trao đổi với client qua socket này, còn socket để listen sẽ đóng lại và có thể nghe trên 1 cổng khác để tiếp nhận 1 client khác.

    Visual C++ Code:
    1. sockaddr_in clientaddr;
    2. SOCKET client = accept (ListenSock, (sockaddr*) &clientaddr, sizeof (clientaddr));
    3. closesocket (ListenSock);

    Nếu muốn, lặp lại quá trình trên để phục vụ 1 client khác:

    Visual C++ Code:
    1. ListenSock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    2. .....

    Tham số thứ hai trong accept sẽ nhận lại thông tin về client yêu cầu kết nối như địa chỉ ip của client... và bạn có thể ngắt kết nối với client này nếu ko muốn và lặp lại quá trình nghe trên ListenSocket.

    Visual C++ Code:
    1. closesocket (client);

    II. Khởi tạo phía client

    B1: Tạo socket TCP

    Visual C++ Code:
    1. SOCKET sock = socket (AF_iNET, SOCK_STREAM, IPPROTO_TCP);

    B2: Kết nối đên server (kết nối đên cái socket đang listen của server)

    Visual C++ Code:
    1. sockaddr_in name;
    2. name.sin_family = AF_INET;
    3. name.sin_addr.s_addr = inet_addr("127.0.0.1");
    4. name.sin_port = htons(4444);
    5. connect (sock, (sockađr*) &name, sizeof (name));

    127.0.0.1 là địa chỉ máy server, vì thử nghiệm sever và client trên cùng 1 máy nên dùng cùng 1 địa chỉ ip.
    4444 là port (cổng) mà socket phía server được bind vào.
    Có thể lấy giá trị lỗi tra về qua hàm WSAGetLastError.

    IV. Gửi và nhận dữ liệu

    Để gửi dữ liệu, ta dùng hàm send:

    send (SOCKET s, const char* buf, int len, int flags);

    s ở phía server trong VD trên là client. ở client là sock.
    buf là thông tin cần gửi. len là kích thước của buf (byte), flag cứ để là 0 cũng được.

    Để nhận dữ liệu ta dùng hàm recv.
    recv (SOCKET s, char* buf, int len, int flags);

    s ở recv cũng giống như send.
    buf là bộ đệm để chứa dữ liệu, len là kích thước tối đa của buf. flags có thể có giá trị MSG_PEEK để copy dữ liệu vào buf, còn bộ đệm của socket vẫn giữ nguyên, nếu ko có giá trị này, bộ đệm của socket sẽ được xóa sau khi copy vào buf.
    Giá trị trả về của recv có thể là:
    0: kết nối đã được ngắt bởi phía server.
    < 0: Đã có lỗi xảy ra. Lấy lỗi bằng WSAGetLastError.
    > 0: kích thước của dữ liệu gửi đến.
    recv là 1 vòng lặp kết thúc đến khi nào có dữ liệu đến hay kết nối bị ngắt, thường dùng 1 thread riêng để xử lí.


    Đây là bài đầu tiên em viết nên có nhiều sai sót, mong mọi người góp ý sửa chữa.
    Đã được chỉnh sửa lần cuối bởi hoanglinh9466 : 30-04-2007 lúc 10:24 PM.
    Life:\> dir

  2. #2
    Ngày gia nhập
    07 2006
    Bài viết
    166

    Mình muốn bổ xung một số điều
    1. Do server phải đáp ứng được khi có nhiều client kết nối đến nên việc lắng nghe kết nối của server được đặt trong một vòng lặp vô hạn, bất cứ khi nào thấy có một kết nối thì sẽ tạo ra một luồng riêng để xử lí kết nối này với client. Đồng thời bên server phải quản lý tất cả các kết nối này (cho vào một mảng chẳng hạn) để phục vụ khi các client muốn trao đổi với nhau

    2. Bên phía client cũng tạo ra một luồng riêng cũng đặt trong vòng lặp vô hạn để trao đổi với server. Chú ý là vòng lặp vô hạn ở 2 phía khác hoàn toàn về mục đích

    Buồn ngủ quá, viết vậy chả biết có gì sai sót không

  3. #3
    Ngày gia nhập
    06 2009
    Bài viết
    9

    mình có làm 1 ứng dụng gửi và nhận mail theo các bạn hướng dẫn(chỉ viết chương trình gửi và nhận mail thôi, còn server thì kiếm 1 con free,ví dụ như con: ArGoSoftMailserver).khi cài con server này trên máy mình thì chạy rất ngon,nhưng khi cài sang máy khác thì mình ko kết nối đến đc.xin hỏi có cách nào khắc phục ko?mình có hỏi qua 1 số bạn bè, thấy bảo là khi viết ctrinh thì fai làm đa luồng, mình lại ko rõ về vđề này,các bạn có thể giúp m ko

  4. #4
    Ngày gia nhập
    06 2009
    Bài viết
    9

    ah cho mình hỏi thêm chút nữa là, nếu khắc phục được như vậy thì ứng dụng của mình có thể gửi và nhận mail từ yahoo,gmail đc chứ

  5. #5
    Ngày gia nhập
    10 2008
    Nơi ở
    Quảng Trị
    Bài viết
    369

    Máy khác mà bạn nói nằm cùng mạng LAN hay là WAN? Nếu là WAN thì phải mở cổng modem ở phía server. Nếu mà bạn cài trên máy bạn mà chạy tốt thì mình nghĩ là do bạn chưa mở cổng cho modem bên server.
    Born to walk against the wind... Born to hear my name...
    Stand and fight... Live by your heart...
    Always one more try... I'm not afraid to die...
    Stand and fight... say what you feel...
    Born with a heart of steel ...

  6. #6
    Ngày gia nhập
    04 2011
    Bài viết
    1

    Mặc định Cấu trúc hàm

    Hàm accept mà bạn nêu ở trên không chính xác không đúng cấu trúc
    tham số cuối của hàm accept phải là
    SOCKADDR_IN clientAddr;
    int clientAddrlen=sizeof(clientAddr);
    tham số cuối phải là &clientAddrlen
    thế mới đúng
    và cái accept thì chỉ phía Server của giao thức TCP mới cần thôi
    mà các bạn cũng có viết cho client và Server theo TCP có thể gửi nhận đồng thời và Server có thể tiếp nhận nhiều client đến!

Các đề tài tương tự

  1. Trả lời: 6
    Bài viết cuối: 28-06-2014, 12:02 PM
  2. Socket Không thể xóa Client ngắt kết nối với Server trong danh sách Client đang kết nối
    Gửi bởi thanhtanh trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 1
    Bài viết cuối: 20-10-2012, 04:37 PM
  3. Chạy ứng dụng client/server vc++ trên 2 máy, làm thế nào để client kết nối server?
    Gửi bởi hotritam365 trong diễn đàn Thắc mắc lập trình Visual C++
    Trả lời: 5
    Bài viết cuối: 12-07-2012, 10:20 PM
  4. Có cần cài SQlServer trên máy Client, trong ứng dụng Server Client
    Gửi bởi billsang trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 4
    Bài viết cuối: 28-10-2011, 01:09 PM
  5. Giao tiếp giữa Client và Server trong lập trình C#?
    Gửi bởi Ding trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 3
    Bài viết cuối: 23-05-2011, 03:04 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn