Linux 下 socket 编程介绍及 TCP 客户端与服务端创建示例

目录

    • socket 编程接口
    • TCP 服务端
    • TCP 客户端
    • 更多内容

本文介绍了 Linux 下的 socket 编程,及总结了使用 socket 接口实现 TCP 服务端和客户端的示例代码。

socket 编程接口

  • socket() 函数:用于创建一个新的 socket 描述符:
int socket(int domain, int type, int protocol);

其中,domain 指定协议族(如 AF_INET 表示 IPv4),type 指定 socket 类型(如 SOCK_STREAM 表示 TCP,SOCK_DGRAM 表示 UDP),protocol 通常设置为 0,表示使用默认协议。

  • bind() 函数:将 socket 绑定到一个 IP 地址或端口上:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

其中,sockfd 是 socket 描述符,addr 是指向 struct sockaddr 的指针,包含了 IP 地址和端口号信息,addrlen 是 struct sockaddr 的大小。

  • listen() 函数:用于监听一个 socket 上的连接请求:
int listen(int sockfd, int backlog);

其中,sockfd 是 socket 描述符,backlog 指定了等待连接的最大队列长度。

  • accept() 函数:从监听 socket 的等待队列中接受一个连接:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

该函数返回一个新的 socket 描述符,用于与客户端进行通信,addr 和 addrlen 用于获取客户端的地址信息。

  • connect() 函数:用于建立一个到服务器的连接:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

其中,sockfd 是 socket 描述符,addr 是指向 struct sockaddr 的指针,包含了服务器的 IP 地址和端口号信息。

  • send() 和 recv() 函数:用于通过 socket 发送和接收数据:
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

其中,sockfd 是 socket 描述符,buf 是指向数据缓冲区的指针,len 是缓冲区的大小,flags 是控制函数行为的标志。

  • close() 函数:用于关闭一个 socket:
int close(int sockfd);

其中,sockfd 是 socket 描述符。

  • 在 Linux 下进行 socket 编程时,通常还需要处理错误和异常情况,以及进行地址转换(使用 inet_ntop 和 inet_pton 函数)和字节序转换(使用 htons 和 ntohs 函数)等操作。

TCP 服务端

  • tcp_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/time.h>
#include <errno.h>
#include "tcp_server.h"char buffer[BUFFER_SIZE] = {0};int server_init_socket(void) 
{int socket_fd;struct sockaddr_in address;if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);if (bind(socket_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}if (listen(socket_fd, 3) < 0) {perror("listen");exit(EXIT_FAILURE);}return socket_fd;
}int server_set_socket_timeout(int socket_fd, long milliseconds)
{struct timeval tv;tv.tv_sec =  milliseconds / 1000; tv.tv_usec = (milliseconds % 1000) * 1000;if (setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) < 0) {perror("setsockopt SO_RCVTIMEO");exit(EXIT_FAILURE);}return 0;
}int server_accept_client(int socket_fd) 
{struct sockaddr_in address;int addrlen = sizeof(address);int temp_fd = accept(socket_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);if (temp_fd < 0) {perror("accept");exit(EXIT_FAILURE);}printf("Connection established with %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));return temp_fd;
}int server_receive_data(int socket_fd, char *message, ssize_t *size) 
{ssize_t bytes_received = recv(socket_fd, message, BUFFER_SIZE, 0);if (bytes_received == -1) {if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ETIMEDOUT){printf("socket recv time out \r\n");return 1;} else {perror("recv");exit(EXIT_FAILURE);}}*size = bytes_received;return 0;
}void server_send_data(int socket_fd, const char *message, ssize_t size) 
{if (send(socket_fd, message, size, 0) < 0) {perror("send");exit(EXIT_FAILURE);}
}int server_check_tcp_connection(int socket_fd) 
{int error = 0;socklen_t len = sizeof(error);if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0) {if (error == 0) {return 1;}}return 0;
}int server_close_socket(int socket_fd) 
{close(socket_fd);return 0;
}
  • tcp_server.h
#ifndef __TCP_SERVER__
#define __TCP_SERVER__#include <sys/socket.h>#define PORT 8080
#define BUFFER_SIZE 1024extern char buffer[BUFFER_SIZE];int server_init_socket(void);
int server_accept_client(int socket_fd);
int server_set_socket_timeout(int socket_fd, long milliseconds);
int server_receive_data(int socket_fd, char *message, ssize_t *size) ;
void server_send_data(int socket_fd, const char *message, ssize_t size);
int server_check_tcp_connection(int socket_fd);
int server_close_socket(int fd);#endif
  • main.c
#include <stdio.h>
#include "tcp_server.h"int main(void)
{int server_fd, client_fd;char recv_buffer[1024];ssize_t size = 0;server_fd = server_init_socket();client_fd = server_accept_client(server_fd);server_send_data(client_fd, "Hello TCP!", 10);server_receive_data(client_fd, recv_buffer, &size);printf("%s", recv_buffer);return 0;
}

TCP 客户端

  • tcp_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>#include "tcp_client.h"int client_init_socket(void)
{int socket_fd;struct sockaddr_in server_address;if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}server_address.sin_family = AF_INET;server_address.sin_addr.s_addr = inet_addr(SERVER_IP);server_address.sin_port = htons(SERVER_PORT);if (connect(socket_fd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) {perror("connect");exit(EXIT_FAILURE);}return socket_fd;
}int client_receive_data(int socket_fd, char *message, ssize_t *size) 
{ssize_t bytes_received = recv(socket_fd, message, BUFFER_SIZE, 0);if (bytes_received == -1) {perror("recv");exit(EXIT_FAILURE);}*size = bytes_received;return 0;
}void client_send_data(int socket_fd, const char *message, ssize_t size) 
{if (send(socket_fd, message, size, 0) < 0) {perror("send");exit(EXIT_FAILURE);}
}int client_check_tcp_connection(int socket_fd) 
{int error = 0;socklen_t len = sizeof(error);if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0) {if (error == 0) {return 1;}}return 0;
}int client_close_socket(int socket_fd)
{close(socket_fd);return 0;
}
  • tcp_client.h
#ifndef __TCP_CLIENT_H__
#define __TCP_CLIENT_H__#include <sys/socket.h>#define SERVER_IP "192.168.0.123"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024int client_init_socket(void);
int client_receive_data(int socket_fd, char *message, ssize_t *size);
void client_send_data(int socket_fd, const char *message, ssize_t size);
int client_check_tcp_connection(int socket_fd);
int client_close_socket(int socket_fd);#endif
  • main.c
#include <stdio.h>
#include "tcp_client.h"int main(void)
{int client_fd = 0;char buffer[1024];ssize_t size = 0;client_fd = client_init_socket();client_send_data(client_fd, "Hello TCP!", 10);client_receive_data(client_fd, buffer, &size);printf("%s", recv_buffer);return 0;
}

更多内容

  • CSDN博客:@Hello阿尔法
  • 哔哩哔哩:@Hello阿尔法
  • 知乎:@Hello阿尔法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/716668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux内核MMC框架

1.mmc的概念 1.MMC MultiMedia Card&#xff0c;多媒体存储卡&#xff0c; 但后续泛指一个接口协定&#xff08;一种卡式&#xff09;&#xff0c;能符合这接口的内存器都可称作mmc储存体,工作电压&#xff1a;高电压为2.7&#xff5e;3.6 V&#xff0c;低电压为1.65&#xf…

【微服务】微服务中常用认证加密方案总结

目录 一、前言 二、登录认证安全问题 3.1 认证方式选择 三、常用的加密方案 3.1 MD5加密算法 3.1.1 md5特点 3.1.2 md5原理 3.1.3 md5使用场景 3.2 AES加密算法 3.2.1 AES简介 3.2.2 AES加解原理 3.2.3 AES算法优缺点 3.2.4 AES算法使用场景 3.3 RSA加密算法 3.3…

Flutter Dio进阶:使用Flutter Dio拦截器实现高效的API请求管理和身份验证刷新

Flutter笔记 使用Flutter Dio拦截器实现高效的API请求管理和身份验证刷新 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article…

金融业被网络攻击了怎么办,如何治理和风险控制?

近年来&#xff0c;网络罪犯的人数和复杂程度都在增加&#xff0c;网络罪犯的目标锁定变得更具策略性&#xff0c;更加专注于最大效率和获利。随着有关全球网络犯罪的数据持续涌入&#xff0c;可以看出金融服务企业已然成为头号锁定目标。虽然金融服务企业在网络安全人员、工具…

图论例题解析

1.图论基础概念 概念 &#xff08;注意连通非连通情况&#xff0c;1节点&#xff09; 无向图&#xff1a; 度是边的两倍&#xff08;没有入度和出度的概念&#xff09; 1.完全图&#xff1a; 假设一个图有n个节点&#xff0c;那么任意两个节点都有边则为完全图 2.连通图&…

【MySQL】SQL 优化

MySQL - SQL 优化 1. 在 MySQL 中&#xff0c;如何定位慢查询&#xff1f; 1.1 发现慢查询 现象&#xff1a;页面加载过慢、接口压力测试响应时间过长&#xff08;超过 1s&#xff09; 可能出现慢查询的场景&#xff1a; 聚合查询多表查询表数据过大查询深度分页查询 1.2 通…

错误笔记:Anaconda 错误(闪退、无法安装等) + Pycharm 错误(无法启动)+ python 报错

Anaconda 错误 1、导航器启动中发生-- 闪退 方法一&#xff1a; Windows下&#xff1a; 1&#xff09;使用管理员运行&#xff1a;conda prompt 2&#xff09;执行命令 conda update anaconda-navigator 方法二&#xff1a; 重置Anaconda配置&#xff1a;anaconda-navigator…

C语言第三十四弹---动态内存管理(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 动态内存管理 1、动态内存经典笔试题分析 1.1、题目1 1.2、题目2 1.3、题目3 1.4、题目4 2、柔性数组 2.1、柔性数组的特点 2.2、柔性数组的使用 2.3、…

【c++】计算树的深度和节点数

在C语言中&#xff0c;计算给定树的层数&#xff08;深度&#xff09;和节点总数通常需要使用递归方法。首先&#xff0c;我们需要定义树的节点结构。这里假设我们处理的是一棵二叉树&#xff0c;每个节点有两个子节点&#xff08;左子节点和右子节点&#xff09;。 下面是一个…

5.STL源码解析-算法、仿函数、适配器

算法 STL算法总览 仿函数与适配器 C标准模板库&#xff08;STL&#xff09;是C程序员的得力工具&#xff0c;提供了许多强大而高效的数据结构和算法。在STL中&#xff0c;仿函数&#xff08;Functor&#xff09;和适配器&#xff08;Adapter&#xff09;是两个重要的概念…

C语言文件操作(fputs() 和 puts() 有两个小区别)

fputs() 和 puts() 有两个小区别&#xff1a; 1.puts() 只能向标准输出流输出&#xff0c;而 fputs() 可以向任何流输出。 2.使用 puts() 时&#xff0c;系统会在自动在其后添加换行符&#xff1b;而使用 fputs() 时&#xff0c;系统不会自动添加换行符。 那么这是不是意味着使…

【C++精简版回顾】17.io流,流中提供的函数

1.流含义 2.流类 3.流对象 4.流对象的函数 举例&#xff1a; 要求&#xff1a;数据结构中经常需要对齐输出数据&#xff0c;应该怎么做&#xff1f; 1.头文件 #include<iomanip> 2.创建表格头 cout << setiosflags(ios::left) << setw(8) << "姓名…

BUGKU 网站被黑

打开环境&#xff0c;什么都没发现&#xff0c;使用蚁剑扫描一下&#xff0c;发现shell.php&#xff0c;打开 使用BP抓包&#xff0c;进行爆破 得到密码&#xff1a;hack 进去得到flag

GEE高阶应用python wxee——如何利用来自 GOES-16 和 MODIS 的数据来可视化火灾随时间的进展分析

火灾进展 wxee 是专为处理气象数据而设计的,但它对遥感数据也很有用。在本示例中,我们将了解 wxee 如何利用来自 GOES-16 和 MODIS 的数据来可视化火灾随时间的进展情况。 安装和设定 #!pip install wxeeimport ee import wxeeee.Authenticate() wxee.Initialize(project=x…

每日一类:QLabel深入解析

QLabel是Qt中用于显示文本或图像的控件&#xff0c;属于Qt Widgets模块。它是展示静态内容的理想选择&#xff0c;支持富文本格式&#xff0c;使得文本可以包含不同的字体、颜色和链接。QLabel也可以用来显示图像&#xff0c;包括动态图像。此外&#xff0c;它还支持文本和图像…

【Java面试题】SpringBoot与Spring的区别

主要区别体现几个方面&#xff1a; 1.操作简便性 SpringBoot提供极其快速和简化的操作&#xff0c;使得Spring开发者能更快速上手。它通过提供spring的运行配置&#xff0c;以及为通用spring项目提供许多非功能性特性&#xff0c;进一步简化了开发过程。 2.框架扩展性 Spri…

算法学习——差分

在了解差分之前&#xff0c;我们首先需要知道前缀和的概念。 前缀和简单介绍&#xff1a; 对于一个数组A&#xff0c;要求出A[0]~A[i]的和&#xff0c;我们通常的做法是遍历一边&#xff0c;加起来。但是要求m组这样的和&#xff0c;我们就要花费O(mn)的时间复杂度。显然不合…

【考研数学】汤家凤1800题什么水平?

我觉得汤家凤基础武忠祥强化这个组合非常的不错 汤家凤老师的讲课风格 汤家凤老师的基础课程是大家公认的讲的详细&#xff0c;并且非常照顾基础不好的学生&#xff0c;会把基础知识点掰开揉碎的讲给大家听&#xff0c;在上课过程中&#xff0c;还会把知识点写在A4纸上&#…

试了下新型的360AI搜索

360AI搜索 试了下&#xff0c;感觉还是挺不错的。 比如问这个问题&#xff1a; ERROR 1698 (28000): Access denied for user rootlocalhost 它的回答&#xff1a; 对于ERROR 1698 (28000): Access denied for user rootlocalhost的问题&#xff0c;这通常是由于MySQL密码为…

【Javascript】设计模式之单例模式

文章目录 1、实现单例模式2、透明的单例模式3、用代理实现单例模式4、JavaScript 中的单例模式5、惰性单例6、通用的惰性单例7、小结 定义&#xff1a; 保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点 单例模式是一种常用的模式&#xff0c;有一些对象我们往…