套接字编程入门

套接字编程入门

1. 套接字概述

套接字(Socket)是用于网络通信的端点。通过套接字,程序可以通过网络发送和接收数据。了解套接字编程的基础知识是进行网络编程的第一步。

1.1 套接字的类型

  • 流套接字SOCK_STREAM):基于TCP协议,提供可靠的双向字节流。
  • 数据报套接字SOCK_DGRAM):基于UDP协议,提供无连接的、尽力而为的服务。

1.2 套接字的基本概念

  • IP地址:标识网络上的每个设备,例如 192.168.1.1
  • 端口号:每个服务在某台设备上使用的数字标识,例如 80(HTTP服务)。
  • 地址族:通常是 AF_INET(IPv4)或 AF_INET6(IPv6)。

2. 套接字编程基础

2.1 创建一个套接字

要使用套接字,首先需要创建一个套接字,让我们用TCP作为例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
printf("Socket created successfully!\n");
return 0;
}

2.2 绑定套接字

绑定套接字将它与特定的IP地址和端口关联。

1
2
3
4
5
6
7
8
9
10
11
12
struct sockaddr_in server_addr;

memset(&server_addr, 0, sizeof(server_addr)); // 清零
server_addr.sin_family = AF_INET; // 地址族
server_addr.sin_addr.s_addr = INADDR_ANY; // 自动选择IP地址
server_addr.sin_port = htons(12345); // 端口号

if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
printf("Socket bound to port 12345.\n");

2.3 监听连接

在套接字上监听连接请求。

1
2
listen(sockfd, 5); // 最多5个挂起的连接请求
printf("Listening for connections...\n");

2.4 接受连接

接受来自客户端的连接。

1
2
3
4
5
6
7
8
9
10
int newsockfd;
struct sockaddr_in client_addr;
socklen_t clilen = sizeof(client_addr);

newsockfd = accept(sockfd, (struct sockaddr*)&client_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
printf("Connection accepted!\n");

3. 数据收发

3.1 发送数据

使用 send 函数发送数据给客户端。

1
2
const char *msg = "Hello from server!";
send(newsockfd, msg, strlen(msg), 0);

3.2 接收数据

使用 recv 函数接收数据。

1
2
3
4
char buffer[256];
memset(buffer, 0, 256);
recv(newsockfd, buffer, 255, 0);
printf("Received message: %s\n", buffer);

4. 关闭套接字

在程序结束之前关闭所有打开的套接字。

1
2
3
close(newsockfd);
close(sockfd);
printf("Sockets closed.\n");

5. 完整示例代码

下面是一个简单的回显服务器的完整示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

#define PORT 12345

int main() {
int sockfd, newsockfd;
struct sockaddr_in server_addr, client_addr;
socklen_t clilen;
char buffer[256];

// 创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}

// 绑定
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);

if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}

// 监听
listen(sockfd, 5);
printf("Listening for connections on port %d...\n", PORT);

// 接受连接
clilen = sizeof(client_addr);
newsockfd = accept(sockfd, (struct sockaddr*)&client_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
printf("Connection accepted!\n");

// 数据收发
memset(buffer, 0, 256);
recv(newsockfd, buffer, 255, 0);
printf("Received message: %s\n", buffer);

send(newsockfd, buffer, strlen(buffer), 0); // 回显数据

// 关闭套接字
close(newsockfd);
close(sockfd);
printf("Sockets closed.\n");

return 0;
}

6. 总结

本节介绍了C语言中的基本套接字编程,包括创建套接字、绑定、监听、接受连接以及数据的发送和接收。通过实际示例,你可以建立一个简单的服务器与客户端进行通信。进一步的内容可以扩展到并发处理、多客户端支持等高级主题。

作者

AI教程网

发布于

2024-08-08

更新于

2024-08-10

许可协议