Unix Socket - Chức năng cốt lõi

Chương này mô tả các chức năng socket cốt lõi cần thiết để viết một máy khách và máy chủ TCP hoàn chỉnh.

Sơ đồ sau đây cho thấy toàn bộ sự tương tác giữa Máy khách và Máy chủ:

Chức năng ổ cắm

Để thực hiện I / O mạng, điều đầu tiên quy trình phải làm là gọi hàm socket, chỉ định loại giao thức truyền thông mong muốn và họ giao thức, v.v.

#include <sys/types.h>
#include <sys/socket.h>

int socket (int family, int type, int protocol);

Cuộc gọi này trả về bộ mô tả ổ cắm mà bạn có thể sử dụng trong các cuộc gọi hệ thống sau này hoặc -1 khi bị lỗi.

Thông số

family - Nó chỉ định họ giao thức và là một trong những hằng số được hiển thị bên dưới -

gia đình Sự miêu tả
AF_INET Giao thức IPv4
AF_INET6 Giao thức IPv6
AF_LOCAL Giao thức miền Unix
AF_ROUTE Ổ cắm định tuyến
AF_KEY Ổ cắm Ket

Chương này không đề cập đến các giao thức khác ngoại trừ IPv4.

type- Nó chỉ định loại ổ cắm bạn muốn. Nó có thể nhận một trong các giá trị sau:

Kiểu Sự miêu tả
SOCK_STREAM Ổ cắm luồng
SOCK_DGRAM Datagram socket
SOCK_SEQPACKET Ổ cắm gói có trình tự
SOCK_RAW Ổ cắm thô

protocol - Đối số phải được đặt thành loại giao thức cụ thể được đưa ra bên dưới hoặc 0 để chọn mặc định của hệ thống cho tổ hợp họ và loại đã cho -

Giao thức Sự miêu tả
IPPROTO_TCP Giao thức truyền tải TCP
IPPROTO_UDP Giao thức truyền tải UDP
IPPROTO_SCTP Giao thức vận chuyển SCTP

Các kết nối Chức năng

Các kết nối chức năng được sử dụng bởi một khách hàng TCP thiết lập kết nối với một máy chủ TCP.

#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

Cuộc gọi này trả về 0 nếu nó kết nối thành công với máy chủ, nếu không nó sẽ trả về -1 khi bị lỗi.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

  • serv_addr - Nó là một con trỏ tới struct sockaddr chứa địa chỉ IP đích và cổng.

  • addrlen - Đặt nó thành sizeof (struct sockaddr).

Các ràng buộc Chức năng

Hàm ràng buộc chỉ định địa chỉ giao thức cục bộ cho một ổ cắm. Với các giao thức Internet, địa chỉ giao thức là sự kết hợp của địa chỉ IPv4 32 bit hoặc địa chỉ IPv6 128 bit, cùng với số cổng TCP hoặc UDP 16 bit. Chức năng này chỉ được gọi bởi máy chủ TCP.

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, struct sockaddr *my_addr,int addrlen);

Cuộc gọi này trả về 0 nếu nó liên kết thành công với địa chỉ, nếu không nó sẽ trả về -1 khi bị lỗi.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

  • my_addr - Nó là một con trỏ tới struct sockaddr chứa địa chỉ IP cục bộ và cổng.

  • addrlen - Đặt nó thành sizeof (struct sockaddr).

Bạn có thể tự động đặt địa chỉ IP và cổng của mình

Giá trị 0 cho số cổng có nghĩa là hệ thống sẽ chọn một cổng ngẫu nhiên và giá trị INADDR_ANY cho địa chỉ IP có nghĩa là địa chỉ IP của máy chủ sẽ được chỉ định tự động.

server.sin_port = 0;  		     
server.sin_addr.s_addr = INADDR_ANY;

NOTE- Tất cả các cổng dưới 1024 đều được bảo lưu. Bạn có thể đặt cổng trên 1024 và dưới 65535 trừ khi chúng là cổng được các chương trình khác sử dụng.

Các nghe Chức năng

Hàm lắng nghe chỉ được gọi bởi một máy chủ TCP và nó thực hiện hai hành động:

  • Hàm lắng nghe chuyển đổi một ổ cắm chưa được kết nối thành một ổ cắm thụ động, chỉ ra rằng hạt nhân phải chấp nhận các yêu cầu kết nối đến trực tiếp đến ổ cắm này.

  • Đối số thứ hai của hàm này chỉ định số lượng kết nối tối đa mà hạt nhân phải xếp hàng cho socket này.

#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd,int backlog);

Cuộc gọi này trả về 0 khi thành công, ngược lại nó trả về -1 khi bị lỗi.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

  • backlog - Đó là số lượng kết nối được phép.

Các chấp nhận Function

Hàm chấp nhận được gọi bởi một máy chủ TCP để trả về kết nối đã hoàn thành tiếp theo từ phía trước của hàng đợi kết nối đã hoàn thành. Chữ ký của cuộc gọi như sau:

#include <sys/types.h>
#include <sys/socket.h>

int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

Cuộc gọi này trả về một bộ mô tả không âm khi thành công, nếu không nó sẽ trả về -1 khi bị lỗi. Bộ mô tả trả về được giả định là bộ mô tả ổ cắm máy khách và tất cả các hoạt động đọc-ghi sẽ được thực hiện trên bộ mô tả này để giao tiếp với máy khách.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

  • cliaddr - Nó là một con trỏ tới struct sockaddr chứa địa chỉ IP của máy khách và cổng.

  • addrlen - Đặt nó thành sizeof (struct sockaddr).

Các gửi Function

Các gửi chức năng được sử dụng để gửi dữ liệu qua ổ cắm dòng hoặc ổ cắm datagram được kết nối. Nếu bạn muốn gửi dữ liệu qua ổ cắm dữ liệu KHÔNG KẾT NỐI, bạn phải sử dụng hàm sendto ().

Bạn có thể sử dụng lệnh gọi hệ thống write () để gửi dữ liệu. Chữ ký của nó như sau:

int send(int sockfd, const void *msg, int len, int flags);

Cuộc gọi này trả về số byte được gửi đi, nếu không nó sẽ trả về -1 khi bị lỗi.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

  • msg - Nó là một con trỏ đến dữ liệu bạn muốn gửi.

  • len - Đó là độ dài của dữ liệu bạn muốn gửi (tính bằng byte).

  • flags - Nó được đặt thành 0.

Các recv Chức năng

Hàm recv được sử dụng để nhận dữ liệu qua ổ cắm luồng hoặc ổ cắm dữ liệu ĐÃ KẾT NỐI. Nếu bạn muốn nhận dữ liệu qua ổ cắm dữ liệu KHÔNG KẾT NỐI, bạn phải sử dụng recvfrom ().

Bạn có thể sử dụng lệnh gọi hệ thống read () để đọc dữ liệu. Cuộc gọi này được giải thích trong chương hàm trợ giúp.

int recv(int sockfd, void *buf, int len, unsigned int flags);

Lệnh gọi này trả về số byte được đọc vào bộ đệm, nếu không, nó sẽ trả về -1 khi bị lỗi.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

  • buf - Nó là bộ đệm để đọc thông tin vào.

  • len - Là chiều dài tối đa của bộ đệm.

  • flags - Nó được đặt thành 0.

Các sendto Chức năng

Hàm sendto được sử dụng để gửi dữ liệu qua các ổ cắm dữ liệu KHÔNG KẾT NỐI. Chữ ký của nó như sau:

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

Cuộc gọi này trả về số byte được gửi, nếu không, nó trả về -1 khi bị lỗi.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

  • msg - Nó là một con trỏ đến dữ liệu bạn muốn gửi.

  • len - Đó là độ dài của dữ liệu bạn muốn gửi (tính bằng byte).

  • flags - Nó được đặt thành 0.

  • to - Nó là một con trỏ đến struct sockaddr cho máy chủ lưu trữ nơi dữ liệu phải được gửi đi.

  • tolen - Nó được đặt thành sizeof (struct sockaddr).

Các recvfrom Chức năng

Hàm recvfrom được sử dụng để nhận dữ liệu từ các ổ cắm dữ liệu KHÔNG KẾT NỐI.

int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);

Lệnh gọi này trả về số byte được đọc vào bộ đệm, nếu không, nó trả về -1 khi bị lỗi.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

  • buf - Nó là bộ đệm để đọc thông tin vào.

  • len - Là chiều dài tối đa của bộ đệm.

  • flags - Nó được đặt thành 0.

  • from - Nó là một con trỏ đến struct sockaddr cho máy chủ lưu trữ nơi dữ liệu phải được đọc.

  • fromlen - Nó được đặt thành sizeof (struct sockaddr).

Các gần Chức năng

Hàm đóng được sử dụng để đóng giao tiếp giữa máy khách và máy chủ. Cú pháp của nó như sau:

int close( int sockfd );

Cuộc gọi này trả về 0 khi thành công, ngược lại nó trả về -1 khi bị lỗi.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

Các shutdown Chức năng

Các shutdown chức năng được sử dụng để cách duyên dáng đóng giao tiếp giữa client và server. Chức năng này cho phép kiểm soát nhiều hơn so với chức năng đóng . Dưới đây là cú pháp tắt máy -

int shutdown(int sockfd, int how);

Cuộc gọi này trả về 0 khi thành công, ngược lại nó trả về -1 khi bị lỗi.

Thông số

  • sockfd - Nó là một bộ mô tả ổ cắm được trả về bởi hàm ổ cắm.

  • how - Đặt một trong các số -

    • 0 - chỉ ra rằng không được phép nhận,

    • 1 - cho biết rằng không được phép gửi và

    • 2- chỉ ra rằng cả gửi và nhận đều không được phép. Khi how được đặt thành 2, nó giống như close ().

Các chọn Chức năng

Hàm select cho biết bộ mô tả tệp được chỉ định nào đã sẵn sàng để đọc, sẵn sàng để ghi hoặc có tình trạng lỗi đang chờ xử lý.

Khi một ứng dụng gọi recv hoặc recvfrom , nó sẽ bị chặn cho đến khi dữ liệu đến cho socket đó. Một ứng dụng có thể đang thực hiện các xử lý hữu ích khác trong khi luồng dữ liệu đến trống. Một tình huống khác là khi một ứng dụng nhận dữ liệu từ nhiều ổ cắm.

Việc gọi recv hoặc recvfrom trên một ổ cắm không có dữ liệu trong hàng đợi đầu vào của nó ngăn cản việc nhận dữ liệu ngay lập tức từ các ổ cắm khác. Lệnh gọi chức năng chọn giải quyết vấn đề này bằng cách cho phép chương trình thăm dò tất cả các tay cầm ổ cắm để xem liệu chúng có khả dụng cho các hoạt động đọc và ghi không bị chặn hay không.

Dưới đây là cú pháp của select -

int select(int  nfds, fd_set  *readfds, fd_set  *writefds, fd_set *errorfds, struct timeval *timeout);

Cuộc gọi này trả về 0 khi thành công, ngược lại nó trả về -1 khi bị lỗi.

Thông số

  • nfds- Nó chỉ định phạm vi của bộ mô tả tệp sẽ được kiểm tra. Hàm select () kiểm tra các bộ mô tả tệp trong phạm vi từ 0 đến nfds-1

  • readfds- Nó trỏ đến một đối tượng kiểu fd_set mà ở đầu vào, chỉ định các bộ mô tả tệp được kiểm tra để sẵn sàng đọc và trên đầu ra, cho biết bộ mô tả tệp nào đã sẵn sàng để đọc. Nó có thể là NULL để chỉ ra một tập hợp trống.

  • writefds- Nó trỏ đến một đối tượng kiểu fd_set mà ở đầu vào, chỉ định các bộ mô tả tệp cần được kiểm tra để sẵn sàng ghi và ở đầu ra, cho biết bộ mô tả tệp nào đã sẵn sàng để ghi. Nó có thể là NULL để chỉ ra một tập hợp trống.

  • exceptfds- Nó trỏ đến một đối tượng kiểu fd_set mà ở đầu vào, chỉ định các bộ mô tả tệp cần được kiểm tra các điều kiện lỗi đang chờ xử lý và trên đầu ra cho biết bộ mô tả tệp nào có các điều kiện lỗi đang chờ xử lý. Nó có thể là NULL để chỉ ra một tập hợp trống.

  • timeout- Nó trỏ đến một cấu trúc khoảng thời gian chỉ định khoảng thời gian mà lệnh gọi chọn sẽ thăm dò các bộ mô tả cho hoạt động I / O khả dụng. Nếu giá trị thời gian chờ là 0, thì select sẽ trả về ngay lập tức. Nếu đối số timeout là NULL, thì select sẽ chặn cho đến khi ít nhất một tệp / ổ cắm xử lý sẵn sàng cho một thao tác I / O khả dụng. Nếu không, lựa chọn sẽ trở lại sau khi khoảng thời gian chờ đã trôi qua HOẶC khi ít nhất một bộ mô tả tệp / ổ cắm đã sẵn sàng cho một hoạt động I / O.

Giá trị trả về từ select là số lượng xử lý được chỉ định trong bộ mô tả tệp đã sẵn sàng cho I / O. Nếu đạt đến giới hạn thời gian được chỉ định bởi trường thời gian chờ, hãy chọn trả về 0. Các macro sau tồn tại để thao tác tập hợp bộ mô tả tệp:

  • FD_CLR(fd, &fdset)- Xóa bit cho bộ mô tả tệp fd trong bộ mô tả tệp fdset.

  • FD_ISSET(fd, &fdset)- Trả về giá trị khác 0 nếu bit cho bộ mô tả tệp fd được đặt trong bộ mô tả tệp được fdset trỏ tới và 0 nếu ngược lại.

  • FD_SET(fd, &fdset) - Đặt bit cho bộ mô tả tệp fd trong bộ mô tả tệp fdset.

  • FD_ZERO(&fdset) - Khởi tạo bộ mô tả tập tin fdset có bit 0 cho tất cả các bộ mô tả tập tin.

Hành vi của các macro này không được xác định nếu đối số fd nhỏ hơn 0 hoặc lớn hơn hoặc bằng FD_SETSIZE.

Thí dụ

fd_set fds;

struct timeval tv;

/* do socket initialization etc.
tv.tv_sec = 1;
tv.tv_usec = 500000;

/* tv now represents 1.5 seconds */
FD_ZERO(&fds);

/* adds sock to the file descriptor set */
FD_SET(sock, &fds); 

/* wait 1.5 seconds for any data to be read from any single socket */
select(sock+1, &fds, NULL, NULL, &tv);

if (FD_ISSET(sock, &fds)) {
   recvfrom(s, buffer, buffer_len, 0, &sa, &sa_len);
   /* do something */
}
else {
   /* do something else */
}