基于socket编程实现TCP和UDP的通信流程

socket编程的常用函数,可以参考以下这篇博客

socket编程-----常用socket编程函数icon-default.png?t=N7T8https://blog.csdn.net/ZZZCY2003/article/details/138071210

关于TCP的三次挥手、四次挥手过程和UDP的报文分析可以参考以下两篇博客

计算机网络--运输层icon-default.png?t=N7T8https://blog.csdn.net/ZZZCY2003/article/details/138007052

TCP协议数据传输过程及报文分析icon-default.png?t=N7T8https://blog.csdn.net/ZZZCY2003/article/details/138035752


目录

一、socket

1.1、socket概述

1.2、基本概念

1.3、关键步骤

1.4、在Linux系统上执行socket过程

二、基于socket编程的TCP通信过程

2.1、基于socket编程的TCP通信流程

2.1.1、服务端(service.c)

2.1.1.1、创建socket

2.1.1.2、绑定socket到端口

2.1.1.3、开始监听连接

2.1.1.4、接受客户端连接

2.1.1.5、读取客户端发送的数据

2.1.1.6、发送响应给客户端

2.1.1.7、关闭套接字

2.1.2、客户端(client.c) 

2.1.2.1、创建socket

2.1.2.2、设置服务器地址结构并来连接服务器

2.1.2.3、发送数据给服务器

2.1.2.4、读取服务器的响应

2.1.2.5、关闭套接字

2.2、基于socket编程的TCP通信流程图

2.3、基于socket编程的TCP示例

2.3.1、服务端(service.c)

2.3.2、客户端(client.c)

三、基于socket编程的UDP通信过程

3.1、基于socket编程的UDP通信流程

3.1.1、服务端

3.1.1.1、创建socket

3.1.1.2、设置服务器地址结构

3.1.1.3、绑定socket

3.1.1.4、打印监听信息

3.1.1.5、接收数据

3.1.1.6、关闭socket

3.1.2、客户端

3.1.2.1、创建socket

3.1.2.2、设置服务器地址结构

3.1.2.3、发送数据

3.1.2.4、打印发送信息

3.1.2.5、关闭socket

3.2、基于socket编程的UDP通信流程图

3.3、基于socket编程的UDP通信示例

3.3.1、服务端(service.c)

3.3.2、客户端(client.c)


一、socket

1.1、socket概述

        Socket编程是计算机网络通信中的一种重要技术,它允许不同的计算机程序通过网络进行通信和数据交换。在Socket编程中,一个程序(通常称为客户端)通过创建Socket对象并与另一个程序(通常称为服务器)建立连接,从而进行通信。

1.2、基本概念

  1. IP地址和端口号:IP地址用于标识网络上的设备,而端口号用于标识设备上的特定服务或应用程序。Socket通过组合IP地址和端口号来唯一标识一个网络上的通信端点。

  2. 客户端与服务器:在Socket编程中,通常有一个服务器程序等待客户端的连接请求。一旦连接建立,客户端和服务器就可以互相发送和接收数据。

  3. 流式套接字(SOCK_STREAM):通常用于TCP协议,提供可靠的、面向连接的通信服务。数据按照字节流的形式发送和接收。

  4. 数据报套接字(SOCK_DGRAM):通常用于UDP协议,提供无连接的通信服务。数据以数据报的形式发送和接收,不保证数据的顺序和可靠性。

1.3、关键步骤

  1. 创建Socket:使用socket函数创建一个新的Socket对象。

  2. 绑定(Bind):对于服务器来说,需要将Socket绑定到一个特定的IP地址和端口号上,以便客户端能够连接。

  3. 监听(Listen):服务器Socket使用listen函数开始监听来自客户端的连接请求。

  4. 接受连接(Accept):服务器使用accept函数接受客户端的连接请求,并返回一个新的Socket对象用于与客户端通信。

  5. 连接(Connect):对于客户端来说,使用connect函数向服务器发起连接请求。

  6. 发送和接收数据:使用send或sendto函数发送数据,使用recv或recvfrom函数接收数据。

  7. 关闭Socket:使用close函数关闭Socket连接,释放资源。

1.4、在Linux系统上执行socket过程

假设已经写好服务端代码(service.c)和客户端代码(client.c)(注意:示例用的是C语言代码,且代码已附在文章最下面)

1、开启两个终端,并对服务端代码和客户端代码进行编译。在两个终端中分别执行以下各一条代码,作为服务端和客户端。

gcc service.c -o service
gcc client.c -o client

2、运行服务端,使服务端处于等待连接状态。等待客户端的请求连接。

./service

3、在另一个终端运行客户端,向服务端发出请求连接的请求

./client

4、最后,执行完成!

二、基于socket编程的TCP通信过程

2.1、基于socket编程的TCP通信流程

2.1.1、服务端(service.c)

2.1.1.1、创建socket
//创建socket文件描述符  
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {  
    perror("socket failed");  
    exit(EXIT_FAILURE);  
}  
2.1.1.2、绑定socket到端口
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(PORT);

//绑定socket到端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
	perror("bind failed");
	exit(EXIT_FAILURE);
}
2.1.1.3、开始监听连接
//开始监听连接
if (listen(server_fd, 3) < 0) {
	perror("listen");
	exit(EXIT_FAILURE);
}
2.1.1.4、接受客户端连接
//接受客户端连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
	perror("accept");
	exit(EXIT_FAILURE);
}
2.1.1.5、读取客户端发送的数据
//读取客户端发送的数据
int valread = read(new_socket, buffer, BUFFER_SIZE);
printf("%s\n", buffer);
2.1.1.6、发送响应给客户端
//发送响应给客户端
send(new_socket, hello, strlen(hello), 0);
printf("Hello message sent\n");
2.1.1.7、关闭套接字
//关闭套接字
close(server_fd);
close(new_socket);

2.1.2、客户端(client.c) 

2.1.2.1、创建socket
//创建socket文件描述符
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
	perror("Socket creation error");
	exit(EXIT_FAILURE);
}
2.1.2.2、设置服务器地址结构并来连接服务器
//设置服务器地址结构
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);

//连接到服务器
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
	perror("Connection failed");
	exit(EXIT_FAILURE);
}

printf("Connected to server\n");
2.1.2.3、发送数据给服务器
//发送数据给服务器
if (send(sock, hello, strlen(hello), 0) < 0) {
	perror("Send failed");
	exit(EXIT_FAILURE);
}
printf("Hello message sent\n");
2.1.2.4、读取服务器的响应
//读取服务器的响应
while ((valread = read(sock, buffer, BUFFER_SIZE - 1)) > 0) {
	buffer[valread] = '\0';
	printf("Received from server: %s\n", buffer);
}

if (valread < 0) {
	perror("Read failed");
}
2.1.2.5、关闭套接字
//关闭socket
close(sock);

2.2、基于socket编程的TCP通信流程图

2.3、基于socket编程的TCP示例

2.3.1、服务端(service.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
	int server_fd, new_socket;
	struct sockaddr_in address;
	int opt = 1;
	int addrlen = sizeof(address);
	char buffer[BUFFER_SIZE] = {0};
	const char *hello = "Hello from server";

	//创建socket文件描述符
	if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
		perror("socket failed");
		exit(EXIT_FAILURE);
	}

	//设置socket选项,允许地址重用
	if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
		perror("setsockopt");
		exit(EXIT_FAILURE);
	}

	address.sin_family = AF_INET;
	address.sin_addr.s_addr = inet_addr("127.0.0.1");
	address.sin_port = htons(PORT);

	//绑定socket到端口
	if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
		perror("bind failed");
		exit(EXIT_FAILURE);
	}

	//开始监听连接
	if (listen(server_fd, 3) < 0) {
		perror("listen");
		exit(EXIT_FAILURE);
	}

	//接受客户端连接
	if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
		perror("accept");
		exit(EXIT_FAILURE);
	}

	//读取客户端发送的数据
	int valread = read(new_socket, buffer, BUFFER_SIZE);
	printf("%s\n", buffer);

	//发送响应给客户端
	send(new_socket, hello, strlen(hello), 0);
	printf("Hello message sent\n");
	
	//关闭套接字
	close(server_fd);
	close(new_socket);
	return 0;
}

2.3.2、客户端(client.c)

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <netdb.h>  
  
#define PORT 8080  
#define BUFFER_SIZE 1024  
  
int main() {  
    int sock = 0;  
    struct sockaddr_in serv_addr;  
    char *hello = "Hello from client";  
    char buffer[BUFFER_SIZE] = {0};  
    int valread;  
      
    //创建socket文件描述符  
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {  
        perror("Socket creation error");  
        exit(EXIT_FAILURE);  
    }  
      
    //设置服务器地址结构  
    memset(&serv_addr, 0, sizeof(serv_addr));  
    serv_addr.sin_family = AF_INET;  
    serv_addr.sin_port = htons(PORT);  

      
    //连接到服务器  
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {  
        perror("Connection failed");  
        exit(EXIT_FAILURE);  
    }  
      
    printf("Connected to server\n");  
      
    //发送数据给服务器  
    if (send(sock, hello, strlen(hello), 0) < 0) {  
        perror("Send failed");  
        exit(EXIT_FAILURE);  
    }  
    printf("Hello message sent\n");  
      
    //读取服务器的响应  
    while ((valread = read(sock, buffer, BUFFER_SIZE - 1)) > 0) {  
        buffer[valread] = '\0';  
        printf("Received from server: %s\n", buffer);  
    }  
      
    if (valread < 0) {  
        perror("Read failed");  
    }  
      
    //关闭socket  
    close(sock);  
    return 0;  
}

三、基于socket编程的UDP通信过程

3.1、基于socket编程的UDP通信流程

3.1.1、服务端

3.1.1.1、创建socket
//创建socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("socket creation failed");
	exit(EXIT_FAILURE);
}
3.1.1.2、设置服务器地址结构
//设置服务器地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//具体的ip地址
server_addr.sin_port = htons(SERVER_PORT);
3.1.1.3、绑定socket
//绑定socket
if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
	perror("bind failed");
	exit(EXIT_FAILURE);
}
3.1.1.4、打印监听信息
printf("Server is listening on port %d\n", SERVER_PORT);
3.1.1.5、接收数据
//接收数据
n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&client_addr, &len);
buffer[n] = '\0';
printf("Received from client: %s\n", buffer);
3.1.1.6、关闭socket
//关闭socket
close(sockfd);

3.1.2、客户端

3.1.2.1、创建socket
//创建socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("socket creation failed");
	exit(EXIT_FAILURE);
}
3.1.2.2、设置服务器地址结构
//设置服务器地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
	perror("Invalid address/Address not supported");
	exit(EXIT_FAILURE);
}
3.1.2.3、发送数据
//发送数据
len = sendto(sockfd, (const char *)buffer, strlen(buffer), MSG_CONFIRM,(const struct sockaddr *)&server_addr, sizeof(server_addr));
if (len < 0) {
	perror("sendto failed");
	exit(EXIT_FAILURE);
}
3.1.2.4、打印发送信息

打印一条消息到控制台,表明数据已成功发送到服务器

printf("Message sent to server: %s\n", buffer);
3.1.2.5、关闭socket
//关闭socket
close(sockfd);

3.2、基于socket编程的UDP通信流程图

3.3、基于socket编程的UDP通信示例

3.3.1、服务端(service.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_PORT 8888
#define BUFFER_SIZE 1024

int main() {
	int sockfd;
	struct sockaddr_in server_addr, client_addr;
	socklen_t len = sizeof(client_addr);
	char buffer[BUFFER_SIZE];
	ssize_t n;

	//创建socket
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket creation failed");
		exit(EXIT_FAILURE);
	}

	//设置服务器地址结构
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//具体的ip地址
	server_addr.sin_port = htons(SERVER_PORT);

	//绑定socket
	if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
		perror("bind failed");
		exit(EXIT_FAILURE);
	}

	printf("Server is listening on port %d\n", SERVER_PORT);

	//接收数据
	n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL,
	             (struct sockaddr *)&client_addr, &len);
	buffer[n] = '\0';
	printf("Received from client: %s\n", buffer);

	//关闭socket
	close(sockfd);
	return 0;
}

3.3.2、客户端(client.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8888
#define BUFFER_SIZE 1024

int main() {
	int sockfd;
	struct sockaddr_in server_addr;
	char buffer[BUFFER_SIZE] = "Hello from UDP client!";
	ssize_t len;

	//创建socket
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket creation failed");
		exit(EXIT_FAILURE);
	}

	//设置服务器地址结构
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SERVER_PORT);
	if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
		perror("Invalid address/Address not supported");
		exit(EXIT_FAILURE);
	}

	//发送数据
	len = sendto(sockfd, (const char *)buffer, strlen(buffer), MSG_CONFIRM,
	             (const struct sockaddr *)&server_addr, sizeof(server_addr));
	if (len < 0) {
		perror("sendto failed");
		exit(EXIT_FAILURE);
	}

	printf("Message sent to server: %s\n", buffer);

	//关闭socket
	close(sockfd);
	return 0;
}

  • 38
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Socket编程中,TCPUDP是两种不同的协议。它们之间的最主要的区别在于TCP是面向连接的协议,而UDP是无连接的协议。 在C语言中,我们可以使用socket API来进行TCPUDP的编程。对于TCP,我们需要先建立连接,然后才能进行数据的传输。而对于UDP,则是直接通过sendto()函数发送数据,接收方通过recvfrom()函数接收数据。 以下是一个简单的例子,展示了如何使用socket API实现TCPUDP通信TCP通信: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; char *hello = "Hello from server"; // 创建套接字 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置套接字选项 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } // 绑定地址 address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons( 8080 ); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } // 接受连接 if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); exit(EXIT_FAILURE); } // 发送数据 send(new_socket, hello, strlen(hello), 0); printf("Hello message sent\n"); return 0; } ``` UDP通信: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> int main() { int sockfd; char buffer[1024] = {0}; char *hello = "Hello from server"; struct sockaddr_in servaddr, cliaddr; // 创建套接字 if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket creation failed"); exit(EXIT_FAILURE); } memset(&servaddr, 0, sizeof(servaddr)); memset(&cliaddr, 0, sizeof(cliaddr)); // 设置服务器地址 servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons(8080); // 绑定地址 if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) { perror("bind failed"); exit(EXIT_FAILURE); } int len, n; len = sizeof(cliaddr); // 接收客户端地址信息 n = recvfrom(sockfd, (char *)buffer, 1024, MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len); buffer[n] = '\0'; printf("Client : %s\n", buffer); // 发送数据 sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM, (const struct sockaddr *) &cliaddr, len); printf("Hello message sent.\n"); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值