Muốn làm việc với socket thì việc đầu tiên là phải tạo socket đó. Để làm việc đó cần gọi lệnh socket() với các tham số cần thiết. Hàm trả lại một socket descriptor nếu thành công, -1 nếu có lỗi.
int socket (int family, int type, int protcol)
• Tham số family xác định họ giao thức đợc sử dụng với socket nh đã nói đến ở trện.
AF_UNIX Giao thức nội bộ UNIX
AF_INER Giao thức Internet(TCP/IP)
AF_NS Giao thức Xeror NS
AF_IMPLINK Giao thức lớp IMP
• Tham số type xác định kiểu của liên kết. Những kiểu có thể sử dụng là dạng stream có độ tin cậy cao (SOCK_STREAM), dạng datagram (SOCK_DGRAM) hay dạng thô (SOCK_RAW) cho phép truy nhập tới mức thấp của mạng.
Ví dụ:
AF_UNIX AF_INET AF_NS
SOCK_STREAM Có TCP Có
SOCK_DGRAM Có UDP Có
SOCK_RAW IP Có
Do đó tham số thứ ba xác định chính xác giao thức nào đợc sử dụng cho socket. Tuy vậy trong rất nhiều ứng dụng tham số này không đợc sử dụng.
Lời gọi bind()
Khi mới đợc tạo ra, socket không đợc gắn với bất cứ địa chỉ nào. Nói riêng với TCP/IP là nó cha đợc gán với số hiệu port của tiến trình gửi, số hiệu port của
tiến trình nhận cũng nh địa chỉ IP. Nhiều chơng trình không quan tâm đến số hiệu port và địa chỉ của nó, và dành cho phần mềm giao thức tự gán. Tuy nhiên các chơng trình khác vẫn cần biết đến địa chỉ của mình. Lệnh bind gán thiết lập một địa chỉ local cho socket và đăng ký nó với hệ thống.
int bind(int sock, struct sockaddr * localaddr, int addrlen) Lời gọi bind() đợc sử dụng trong các trờng hợp sau:
• Chơng trình server đăng ký một địa chỉ thông dụng với hệ thống. Mọi dữ liệu đến địa chỉ này sẽ đợc chuyển cho nó.
• Một chơng trình client đăng ký một địa chỉ đặc biệt.
• Một chơng trình client có kiểu không kết nối (connectionless) muốn kiểm tra xem địa chỉ của nó có hợp lệ hay không.
Lời gọi connect
Để thiết lập đợc một liên kết giữa client với server, tiến trình cần phải gọi lệnh connect.
int connect(int sock, struct sockaddr * seraddr, int addrlen)
Tham số lệnh này tơng tự đối với lệnh bind() nhng seraddr trỏ tới địa chỉ của server (tức là đầu kia của liên kết).
• Đối với các giao thức có liên kết (connection-oriented), connect() sẽ tạo lập một liên kết thực sự giữa hai máy. Các thông tin đợc trao đổi nhằm thống nhất mọi tham số liên quan. Nó sẽ cha thoát ra nếu nh cha thiết lập đợc liên kết hoặc cha nhận đợc thông báo lỗi.
• Đối với các giao thức không liên kết (connectionless) lệnh connect() đơn giản chỉ cất giữ địa chỉ server (biến seraddr) để tiến trình sau này sử dụng khi trao đổi dữ liệu. Với giao thức này việc gọi lệnh connect() có thể bỏ qua nhng việc sử dụng nó sẽ tạo ra sự thuận tiện đối với ngời lập trình. Sau khi đăng ký địa chỉ với hệ thống thì sẽ không cần phải xác định lại địa chỉ mỗi khi gửi đi các datagram. Ngời sử dụng có thể dùng các lệnh read, write, recv, send tơng tự nh các socket có kết nối.
Ngoài ra, connect còn kiểm tra xem có thực sự một tiến trình nào nhận thông tin mình sẽ gửi hay không. Nếu địa chỉ gửi không tồn tại connect sẽ trả lại lỗi cho tiến trình gọi. Việc này làm cho tiến trình có thể xử lý lỗi tốt hơn so với các giao thức không kết nối (ví dụ UDP). Một datagram có thể chứa một địa chỉ sai và hoàn toàn không có ngời nhận.
Lời gọi listen()
Ta sẽ xem xét một tiến trình server, tiến trình này đầu tiên tạo ra một socket, gắn nó với một port thông dụng rồi chờ cho đến khi có một yêu cầu đợc gửi tới. Nếu nó là một liên kết kết nối thực sự, hoặc nó phải xử lý quá lâu đối với mỗi yêu cầu, sẽ xảy ra trờng hợp là một yêu cầu mới sẽ tới trong khi yêu cầu cũ cha đợc xử lý xong. Để tránh việc các yêu cầu mới bị từ chối, server phải khai báo với phần mềm của giao thức tạo ra cho nó một hàng đợi các yêu cầu. Lệnh listen() sẽ khai báo hàng đợi này.
int listen(int sock, int qlen)
• Tham số sock là socket descriptor đợc dùng bởi server.
• Tham số qlen quyết định chiều dài hàng đợi các yêu cầu. Giá trị tối đa của tham số này là 5.
Khi hàng đợi này đã đầy, hệ thống sẽ không chấp nhận thêm một yêu cầu nào khác. Mọi yêu cầu tới sau đó sẽ bị huỷ bỏ. listen() chỉ áp dụng với socket kiểu STREAM.
Lời gọi accept()
Sau khi tiến trình server gọi các lệnh socket(), bind(), listen() để tạo ra một socket, gắn nó với một port thông dụng, xác định chiều dài hàng đợi, server sẽ gọi lệnh accept() để tạo ra một kết nối hoàn thiện.
int accept(int sock, struct sockaddr * addr, int addrlen)
Tham số addr dùng để trả lại địa chỉ của tiến trình gửi yêu cầu (client). accept() sẽ lấy yêu cầu đầu tiên trong hàng đợi và tạo ra một socket mới có
cùng thuộc tính với sock. Nếu trong hàng đợi không có một yêu cầu nào thì nó sẽ chờ cho đến khi có một yêu cầu đợc gửi tới. Socket sock vẫn đợc giữ nguyên do vậy server vẫn tiếp tục chấp nhận các yêu cầu khác gửi tới socket này.
Với cách tiếp cận tơng tác, server tự xử lý giải quyết yêu cầu sau đó đóng socket này lại và quay về xử lý tiếp các yêu cầu sau đó.
Còn đối với phơng pháp đồng thời, sau khi lệnh accept() trả lại kết quả server sẽ sinh ra một tiến trình con để giải quyết yêu cầu. Tiến trình con sẽ nhận đợc một bản sao của socket mới. Trong khi đó tiến trình server sẽ lập tức đóng socket mới của nó sau khi tạo ra tiến trình con và trở lại gọi accept() để nhận một yêu cầu mới.
Lời gọi close()
Khi một tiến trình thôi không sử dụng socket thì nó gọi lệnh close() int close(int sock)
sock là socket cần huỷ bỏ. Khi một tiến trình kết thúc với mọi lý do, hệ thống
sẽ đóng tất cả các socket còn mở. Đối với các giao thức tin cậy, mặc dù socket đã bị đóng nhng kernel vẫn cố gắng gửi đi các dữ liệu còn lại trong hàng đợi dữ liệu.
Một số lời gọi gửi dữ liệu qua socket