深入理解Linux Socket系统调用 (linux socket系统调用)
Linux操作系统广泛应用于服务器、互联网、嵌入式设备等领域,其成功的原因之一便是其强大的网络支持。Linux提供了一套完整的Socket编程API,使得程序员可以方便地实现网络应用程序。Socket编程是网络编程的基础,对于开发网络应用程序至关重要。
本文将系统地介绍Linux Socket系统调用相关知识,包括Socket概念、Socket编程模型、Socket系统调用接口、Socket编程应用例程等,并结合应用场景进行实践演示,以期读者能够,掌握Socket编程技术。
一、Socket概念
Socket是一种传输层协议,用于实现进程间的网络通信,是Linux中程序进行网络通信的主要手段。Socket提供了一套完整的API,使得程序员能够方便地进行网络编程。
在网络编程中,Socket常用于描述生成的套接字(socket),套接字是使用网络传输协议进行通信的两个程序之间的一条双向通信链路。套接字可使用网络传输协议TCP、UDP、RAW等。
二、Socket编程模型
Socket编程模型是一种典型的客户端/服务器模型,其中服务器程序和客户端程序分别运行在不同的主机上,通过对套接字API的调用来实现进程间的通信。Socket编程模型通常包括三个要素:服务器、客户端和Socket。
1、服务器
服务器是Socket编程模型中的核心角色,其职责是等待客户端的连接请求,并对连接请求进行处理。服务器通过Socket系统调用创建一个用于侦听连接请求的套接字,并通过accept系统调用对连接请求进行响应,最后通过接受到的客户端请求来完成进程间的通信。
2、客户端
客户端是Socket编程模型中的请求方,其职责是主动与服务器建立Socket连接,并通过Socket传输数据。客户端通过Socket系统调用创建一个用于连接服务器的套接字,并通过connect系统调用与服务器建立连接。建立连接后,客户端可以使用send和recv系统调用来发送和接受数据。
3、Socket
Socket是Socket编程模型中进程间通信的主要手段,其实现方式与文件读写类似,可以使用系统调用对其进行读写操作。对于服务器端,Socket主要用来侦听客户端连接请求,创建客户端与服务器之间的连接;对于客户端,Socket主要用来主动发起连接请求,并完成数据传输操作。
三、Socket系统调用
Socket系统调用是Linux操作系统提供的一套API接口,用于操作Socket。Socket系统调用为Socket编程提供了多种API,包括创建Socket、建立连接、发送数据、接收数据等。
以下是常用的Socket系统调用:
1、socket:创建一个新的Socket,返回套接字描述符。
2、bind:将地址和端口号绑定到Socket上。
3、listen:开始监听来自客户端的连接请求。
4、accept:接收客户端的连接请求,返回一个新的套接字描述符。
5、connect:主动与服务器建立连接。
6、send:向已连接的Socket中发送数据。
7、recv:从已连接的Socket中接收数据。
8、shutdown:关闭Socket的发送或接收通道。
四、Socket编程应用例程
下面通过一个简单的Socket编程应用例子来说明Socket编程的具体应用。
使用Socket编写一个简单的服务器来接受客户端的输入,并将其发送回客户端。
1、服务器端程序演示代码:
“`
#include
#include
#include
#include
#include
#include
#include
int mn(void)
{
int server_fd, client_fd;
socklen_t client_len;
struct sockaddr_in server_addr, client_addr;
char buffer[1024];
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(30001);
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror(“server: socket error”);
exit(1);
}
if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror(“server: bind error”);
exit(1);
}
if (listen(server_fd, 5) == -1) {
perror(“server: listen error”);
exit(1);
}
printf(“server wting for client on port 30001…\n”);
while (1) {
client_len = sizeof(client_addr);
client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);
if (client_fd == -1) {
perror(“server: accept error”);
continue;
}
printf(“server: connection from client %s\n”, inet_ntoa(client_addr.sin_addr));
while (1) {
memset(buffer, 0, sizeof(buffer));
if (recv(client_fd, buffer, sizeof(buffer), 0) == -1) {
perror(“server: receive error”);
break;
}
if (strcmp(buffer, “quit\n”) == 0) {
printf(“server: client %s quits\n”, inet_ntoa(client_addr.sin_addr));
break;
}
printf(“server: receive message %s”, buffer);
if (send(client_fd, buffer, strlen(buffer), 0) == -1) {
perror(“server: send error”);
break;
}
}
close(client_fd);
}
close(server_fd);
return 0;
}
“`
2、客户端程序演示代码:
“`
#include
#include
#include
#include
#include
#include
#include
#include
int mn(int argc, char *argv[])
{
int client_fd, numbytes;
struct hostent *he;
struct sockaddr_in server_addr;
char message[1024];
if (argc != 2) {
fprintf(stderr, “usage: client hostname\n”);
exit(1);
}
if ((he = gethostbyname(argv[1])) == NULL) {
perror(“client: gethostbyname error”);
exit(1);
}
if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror(“client: socket error”);
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr = *((struct in_addr*)he->h_addr);
server_addr.sin_port = htons(30001);
if (connect(client_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror(“client: connect error”);
exit(1);
}
printf(“client: connected to server %s\n”, argv[1]);
while (1) {
memset(message, 0, sizeof(message));
fgets(message, sizeof(message), stdin);
if (strcmp(message, “quit\n”) == 0) {
printf(“client quits\n”);
break;
}
if (send(client_fd, message, strlen(message), 0) == -1) {
perror(“client: send error”);
exit(1);
}
if ((numbytes = recv(client_fd, message, sizeof(message), 0)) == -1) {
perror(“client: recv error”);
exit(1);
}
message[numbytes] = ‘\0’;
printf(“client: receive message %s”, message);
}
close(client_fd);
return 0;
}
“`
运行结果:
1、服务器端运行结果
“`
server wting for client on port 30001…
server: connection from client 127.0.0.1
server: receive message abc
server: receive message def
server: client 127.0.0.1 quits
“`
2、客户端运行结果
“`
client: connected to server 127.0.0.1
abc
client: receive message abc
def
client: receive message def
quit
client quits
“`
以上代码演示了一个简单的Socket编程应用,该应用实现了客户端和服务器端的互相通信,可以作为Socket编程的入门代码进行学习和研究。
: