Stream Socket dựa trên giao thức TCP việc truyền dữ liệu chỉ thực hiện giữa 2 quá trình đã thiết lập kết nối. Giao thức này đảm bảo dữ liệu được truyền đến nơi nhận một cách đáng tin cậy, đúng thứ tự nhờ vào cơ chế quản lý luồng lưu thông trên mạng và cơ chế chống tắc nghẽn.
- Ưu điểm của Stream Socket là gì?
- Dữ liệu truyền đi được đảm bảo truyền đến đúng nơi nhận, đúng thứ tự.
- Mỗi thông điệp gửi đi đều có xác nhận trả về để thông báo cho người dùng thông tin về quá trình truyền tải.
- Nhược điểm:
- Giữa máy chủ và máy nhận chỉ có 1 IP, nên khi kết nối, 1 máy phải chờ máy còn lại chấp nhận kết nối.
- Tốc độ không nhanh
- Nó phù hợp ứng dụng trong các ứng dụng yêu cầu độ chính xác cao, không yêu cầu cao về tốc độ. Ta có thể kể đến 1 vài ứng dụng như: Mail, thanh toán ngân hàng , ...
Datagram Socket
- Dựa trên giao thức UDP việc truyền dữ liệu không yêu cầu có sự thiết lập kết nối giữa 2 quá trình.
- Ưu điểm của Datagram Socket là gì?
- Quá trình kết nối và truyền tải thông tin đơn giản, không cần thực hiện nhiều thao tác.
- Thời gian truyền tải dữ liệu cực nhanh.
- Nhược điểm
- Quá trình truyền thông tin không đảm bảo tin cậy, thông tin có thể truyền sai thứ tự hoặc bị lặp.
- Phù hợp với các ứng dụng như live stream, video call, ... vì những ứng dụng này yêu cầu tốc độ nhanh, nếu mất mát 1 vài gói tin trong lúc truyền thì vẫn không ảnh hưởng quá nhiều.
Có bao giờ bạn thắc mắc những chương trình bạn viết ra hoạt động, giao tiếp thế nào trong mạng máy tính chưa? Hay dễ hiểu là làm cách nào để server của bạn có thể nói chuyện được với client?
Lập trình mạng là một trong những nhiệm vụ căn bản để phát triển các ứng dụng. Một chương trình mạng được viết ra để các chương trình trên các máy tính khác nhau có thể truyền tin với nhau một cách hiệu quả và an toàn cho dù chúng được cài đặt trên mạng LAN, WAN hay mạng toàn cầu Internet, đây là điều căn bản đối với sự thành công của nhiều hệ thống.
Hãy cùng mình nghịc thử để viết 1 chương trình socket giao tiếp client và server đơn giản nhất!
Giới thiệu về Socket
SocKet là một giao diện lập trình [API – Application Program Interface] ứng dụng mạng thông qua giao diện này có thể lập trình điều khiển việc truyền thông giữa 2 máy sử dụng các giao thức mức thấp như TCP,UDP… , Có thể tưởng tượng nó như một thiết bị truyền thông 2 chiều tương tự như tệp tin, chúng ta gửi/nhận dữ liệu giữa 2 máy, tương tự như việc đọc ghi trên tệp tin. Với mô hình khách chủ TCP
Bây giờ chúng ta sẽ bắt tay tìm hiểu cách làm và thực hànhViết chương trình phía server
Các bước để tạo lên 1 chương trình phía server:
socket [int family, int type, int protocol]
các tham số trong đó theo thứ tự là họ giao thức, kiểu socket, kiểu giao thức. Gán địa chỉ cho socketbind [int sockfd, const struct sockaddr *sockaddr, socklen_t addrlen]
các tham số lần lượt là mô tả socket vừa tạo, con trỏ chỏ đến địa chỉ socket, độ lớn địa chỉ Chỉ định socket lắng nghe kết nốilisten [int sockfd, int backlog]
trong đó sockfd là mô tả socket vừa tạo, backlog là số lượng tối đa các kết nối đang chờ Chờ/chấp nhận kết nốiaccept [int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen]
lần lượt có các tham số là mô tả socket vừa tạo, con trỏ tới cấu trúc địa chỉ socket của tiến trình kết nối đến, độ lớn cấu trúc địa chỉ Thiết lập kết nối với máy chủ TCPconnect [int sockfd, const struct sockaddr *servaddr, socklen_t addrlen]
Viết chương trình phía client
Các bước để tạo lên 1 chương trình phía client
Tạo socket với hàmsocket [int family, int type, int protocol]
các tham số trong đó theo thứ tự là họ giao thức, kiểu socket, kiểu giao thức. Connect tới địa chỉ server với hàm `connect[sock, [struct sockaddr ]&serv_addr, sizeof[serv_addr] - Đọc dữ liệu từ server và ghi vào biến buffer `read[ sock , buffer, 1024]
Sau đây mình sẽ đi vào thực hành với 1 requirement đơn giản là: Mô tả chương trình:
Code phía server
`
include
include
include
include
include
include
include
define PORT 8080
int main[int argc, char const *argv[]] {
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof[address];
char mess_from_client[225];
char buffer[1024] = {0};
char *hello = "Hello from server";
int continu = 1;
//tao socket
// tao file mo ta soket
if [[server_fd = socket[AF_INET, SOCK_STREAM, 0]] == 0]
{
perror["socket failed"];
exit[EXIT_FAILURE];
}
//gan dia chi cho socket
// gan cong port 8080
if [setsockopt[server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof[opt]]]
{
perror["setsockopt"];
exit[EXIT_FAILURE];
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons[ PORT ]; //gan cong la 8080
// bind
if [bind[server_fd, [struct sockaddr *]&address, sizeof[address]]sin_port]];
printf["Tin nhan ban nhan dc tu client: \n"];
//read, doc du lieu gan vao bien valread tra ve so byte ma no doc duoc
valread = read[ new_socket, buffer, 1024];
//viet hoa
ToUp[buffer];
//gan bien hello tra ve cho client la buffer da viet hoa
hello = &buffer;
printf["%s\n",buffer ];
send[new_socket, hello, strlen[hello], 0 ];
}
close[new_socket];
return 0;
}
void ToUp[ char *p ]
{
while[ *p ]
{ *p=toupper[ *p ];
p++;
}
} `
# include
# include
# include
# include
# include
# define PORT 8080
int main[int argc, char const *argv[]]
{
struct sockaddr_in address;
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
char add[225];
int continu = 1;
printf["Nhap dia chi server\n"];
gets[add];
//tao socket
if [[sock = socket[AF_INET, SOCK_STREAM, 0]] < 0]
{
printf["\n Socket creation error \n"];
return -1;
}
memset[&serv_addr, '0', sizeof[serv_addr]];
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons[PORT];
// Convert IPv4 and IPv6 addresses from text to binary form
if[inet_pton[AF_INET, add, &serv_addr.sin_addr]