文章目录
-
- [1. 什么是Socket?](#1. 什么是Socket?)
-
- [1.1 Socket接口简介](#1.1 Socket接口简介)
- [2. 基于Socket的TCP通信](#2. 基于Socket的TCP通信)
-
- [2.1 TCP通信流程](#2.1 TCP通信流程)
- [2.2 TCP编程实例](#2.2 TCP编程实例)
- [3. 基于Socket的UDP通信](#3. 基于Socket的UDP通信)
-
- [3.1 UDP通信流程](#3.1 UDP通信流程)
- [3.2 UDP编程实例](#3.2 UDP编程实例)
- 总结
在网络编程中, Socket 是一种强大的工具,它在应用层和传输层之间提供了一个抽象层,使得复杂的网络通信变得简单易用。本文将为基础小白介绍 UDP和TCP套接字编程 的基本概念、工作原理及实际应用,帮助大家更好地理解和应用这些技术。
1. 什么是Socket?
Socket 是在应用层和传输层之间的一个抽象层,它将TCP/IP层复杂的操作抽象为几个简单的接口,供应用层调用以实现进程在网络中的通信。Socket起源于UNIX,在Unix的"一切皆文件"哲学下,Socket是一种"打开---读/写---关闭"模式的实现,服务器和客户端各自维护一个"文件",在建立连接后,可以向自己文件写入内容供对方读取,或读取对方内容,通信结束时关闭文件。
1.1 Socket接口简介
- socket() :创建Socket
- bind() :绑定Socket到本地地址和端口,通常由服务端调用
- listen() :TCP专用,开启监听模式
- accept() :TCP专用,服务器等待客户端连接,一般是阻塞态
- connect() :TCP专用,客户端主动连接服务器
- send() :TCP专用,发送数据
- recv() :TCP专用,接收数据
- sendto() :UDP专用,发送数据到指定的IP地址和端口
- recvfrom() :UDP专用,接收数据,返回数据远端的IP地址和端口
- close() :关闭Socket
2. 基于Socket的TCP通信
TCP(传输控制协议) 是一种面向连接的可靠传输协议,在数据传输之前需要建立连接,这个过程通常称为三次握手。TCP保证数据传输的可靠性,因此适用于需要高可靠性的场景。
2.1 TCP通信流程
服务端(被动连接,需要创建自己的地址信息):
- 创建一个套接字 :
socket()
- 绑定IP地址、端口等信息到Socket上 :
bind()
- 监听套接字 :
listen()
- 等待客户端的连接请求 :
accept()
- 发送、接收数据 :
send()
和recv()
,或者read()
和write()
- 关闭网络连接 :
close()
客户端:
- 创建一个套接字 :
socket()
- 连接服务器 :
connect()
- 接收、发送数据 :
send()
和recv()
,或者read()
和write()
- 关闭网络连接 :
close()
2.2 TCP编程实例
服务端(service.c) :
c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(1258);
bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(serv_sock, 20);
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_size = sizeof(clnt_addr);
int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
char str[] = "Hello World!";
write(clnt_sock, str, sizeof(str));
close(clnt_sock);
close(serv_sock);
return 0;
}
客户端(client.c) :
c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(1258);
connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
char buffer[40];
read(sock, buffer, sizeof(buffer) - 1);
printf("Message from server: %s\n", buffer);
close(sock);
return 0;
}
利用python具体案例请点击------->》python课程设计作业-TCP客户端-服务端通信-CSDN博客
3. 基于Socket的UDP通信
UDP(用户数据报协议) 是一种无连接的传输协议,数据传输时不需要建立连接,直接发送数据到目标地址即可。UDP适用于实时性要求高的数据传输场景,例如视频直播、在线游戏等。
3.1 UDP通信流程
服务端:
- 建立套接字文件描述符 :
socket()
- 设置服务器IP地址和端口,初始化要绑定的网络地址结构
- 绑定IP地址、端口等信息 :
bind()
- 循环接收客户端的数据 :
recvfrom()
- 向客户端发送数据 :
sendto()
- 关闭套接字 :
close()
客户端:
- 建立套接字文件描述符 :
socket()
- 设置服务器IP地址和端口 :
struct sockaddr
- 向服务器发送数据 :
sendto()
- 接收服务器的数据 :
recvfrom()
- 关闭套接字 :
close()
3.2 UDP编程实例
服务端(service.c) :
c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#define SERV_PORT 3000
int main() {
int sock_fd;
int recv_num;
int send_num;
int client_len;
char recv_buf[20];
struct sockaddr_in addr_serv;
struct sockaddr_in addr_client;
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0) {
perror("socket");
exit(1);
} else {
printf("sock successful\n");
}
memset(&addr_serv, 0, sizeof(struct sockaddr_in));
addr_serv.sin_family = AF_INET;
addr_serv.sin_port = htons(SERV_PORT);
addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
client_len = sizeof(struct sockaddr_in);
if (bind(sock_fd, (struct sockaddr *)&addr_serv, sizeof(struct sockaddr_in)) < 0) {
perror("bind");
exit(1);
} else {
printf("bind successful\n");
}
while (1) {
printf("begin recv:\n");
recv_num = recvfrom(sock_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&addr_client, &client_len);
if (recv_num < 0) {
printf("bad\n");
perror("recvfrom");
exit(1);
} else {
recv_buf[recv_num] = '\0';
printf("recv successful:%s\n", recv_buf);
}
printf("begin send:\n");
send_num = sendto(sock_fd, recv_buf, recv_num, 0, (struct sockaddr *)&addr_client, client_len);
if (send_num < 0) {
perror("sendto");
exit(1);
} else {
printf("send successful\n");
}
}
close(sock_fd);
return 0;
}
客户端(client.c) :
c
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define DEST_PORT 3000
#define DEST_IP_ADDRESS "192.168.1.103"
int main() {
int sock_fd;
int send_num;
int recv_num;
int dest_len;
char send_buf[20] = {"hello tiger"};
char recv_buf[20];
struct sockaddr_in addr_serv;
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&addr_serv, 0, sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
addr_serv.sin_addr.s_addr = inet_addr(DEST_IP_ADDRESS);
addr_serv.sin_port = htons(DEST_PORT);
dest_len = sizeof(struct sockaddr_in);
printf("begin send:\n");
send_num = sendto(sock_fd, send_buf, sizeof(send_buf), 0, (struct sockaddr *)&addr_serv, dest_len);
if (send_num < 0) {
perror("sendto");
exit(1);
} else {
printf("send successful:%s\n", send_buf);
}
recv_num = recvfrom(sock_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&addr_serv, &dest_len);
if (recv_num < 0) {
perror("recvfrom");
exit(1);
} else {
printf("recv successful\n");
}
recv_buf[recv_num] = '\0';
printf("the receive:%s\n", recv_buf);
close(sock_fd);
return 0;
}
总结
通过本文的介绍,我们学习了Socket编程 的基本概念和应用,包括TCP 和UDP 两种网络通信协议的编程方法。Socket作为网络编程的基础工具,使得复杂的网络通信变得更加简洁易用。希望通过本文的学习,大家能够更好地理解和应用Socket编程,为进一步的网络编程打下坚实的基础。