Socket编程--TCP连接以及并发处理

news2025/1/12 22:53:55

流程图

网络传输流程:
在这里插入图片描述
TCP连接:
在这里插入图片描述

api

客户端:

  • socket: 创建套接字
    domain: AF_INET :IPv4
    type: SOCK_STREAM(tcp)、SOCK_DGRAM(udp)
    protocol: 0 默认协议
    返回值:成功返回一个新的套接字,失败返回­1,设置errno
int socket(int domain, int type, int protocol);

  • connect: 连接服务器(客户端执行)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockdf:
参数是成功调用socket()返回的套接字。
addr:
传入参数,指定服务器端地址信息,含IP地址和端口号
addrlen:
传入参数,如IPV4传入sizeof(struct sockaddr_in)大小
如果调用成功,表示连接已经建立(三次握手完成),返回0。否则返回 ­1并将错误码代存放于全局变量errno
之中。

服务端:

  • bind: 给本地套接字赋予地址和端口号
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:
socket套接字
addr:
填写IP地址、端口号、协议族等信息。
addrlen:
addr结构体实例的大小
返回值:
成功返回0,失败返回­1, 设置errno
  • listen : 给连接排队
int listen(int sockfd, int backlog);
sockfd:
参数为成功调用socket函数返回的套接字,并已经成功调用了bind()。
backlog:
参数告诉套接字在忙于处理上一个请求时,还可以接受多少个进入的请求,换句话说,这决定了挂起连接的队
列的大小。
  • accept: 等待客户
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockdf:
参数为成功调用socket函数返回的套接字,并已经成功调用了 bind()listen()
addr:
传出参数,返回连接客户端地址信息,含IP地址和端口号。(如果使用IPv4地址族,那么它需要我们填个指向
sockaddr_in结构的指针)
addrlen:
传入传出参数(值­结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小
返回值:
成功返回一个新的socket文件描述符,用于和客户端通信,失败返回­1,设置errn

Socket IO:

  • send:客户端/服务器发送数据
 int send( SOCKET s, const char FAR *buf, int len, int flags ); 
 // flag 通常为0
  • recv:客户端/服务器接收数据
int recv( SOCKET s, char FAR *buf, int len, int flags); 
  • read
int read(int sockfs, void *buf, size_t nbytes);
  • write
int write(int sockfd, void *buf, size_t nbytes);

阻塞IO/非阻塞IO

阻塞:等待某个条件的满足才能往下执行,非阻塞反之。

设置非阻塞模式:

int flag = fcntl(sockfd,F_GETFL,0);
flags |= O_NONBLOCK;
fcntl(sockfd,F_SETFL,flags);

阻塞IO:
accept(), 需要等待客户端连接, 之后继续执行
recv() 等待数据到来后继续执行
如果设置非阻塞模式,则不需要进行等待

code

连接一个客户端收发数据:
一个客户端连接对应一个accept,在listen()执行后,accept()未执行前,客户端进行连接,accept 可以成功连接,并返回新的socket的值 , while循环处理send/recv

连接多个客户端进行收发数据:
创建线程,循环读取数据, 在while循环中, 调用accept和线程

客户端:

#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SERVER_PORT 9999
int main(int argc, char *argv[])
{
	struct sockaddr_in serveraddr;
	int sockfd, n, ret;
	char buf[] = "helloworld";
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	bzero(&serveraddr, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	inet_pton(AF_INET, "127.0.0.1", &serveraddr.sin_addr);
	serveraddr.sin_port = htons(SERVER_PORT);
	ret = connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
	if(ret ==1)
	perror("connect");
	ret = send(sockfd, buf, strlen(buf),0);
	if(ret ==1)
	perror("connect");
	close(sockfd);
	return 0;
}

服务器端:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>

#define BUFFER_LENGTH	128

void *routine(void *arg) {

	int clientfd = *(int *)arg;

	while (1) {
		
		unsigned char buffer[BUFFER_LENGTH] = {0};
		int ret = recv(clientfd, buffer, BUFFER_LENGTH, 0);
		if (ret == 0) {
			close(clientfd);
			break;
			
		}
		printf("buffer : %s, ret: %d\n", buffer, ret);

		ret = send(clientfd, buffer, ret, 0); // 

	}
}
int main() {
// block
	int listenfd = socket(AF_INET, SOCK_STREAM, 0);  // 
	if (listenfd == -1) return -1;
// listenfd
	struct sockaddr_in servaddr;
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(9999);

	if (-1 == bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) {
		return -2;
	}

#if 0 // nonblock
	int flag = fcntl(listenfd, F_GETFL, 0);
	flag |= O_NONBLOCK;
	fcntl(listenfd, F_SETFL, flag);
#endif

	listen(listenfd, 10);

	while (1) {
		
		struct sockaddr_in client;
		socklen_t len = sizeof(client);
		int clientfd = accept(listenfd, (struct sockaddr*)&client, &len);
		
		pthread_t threadid;
		pthread_create(&threadid, NULL, routine, &clientfd);

	}
}

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

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

相关文章

RakSmart站群服务器租用注意事项科普

随着互联网的飞速发展&#xff0c;站群运营成为越来越多企业和个人的选择。而RakSmart作为知名的服务器提供商&#xff0c;其站群服务器租用服务备受关注。在租用RakSmart站群服务器时&#xff0c;源库建议有一些关键的注意事项需要特别留意&#xff0c;以确保服务器的稳定运行…

ThinkPHP5 SQL注入漏洞敏感信息泄露漏洞

1 漏洞介绍 ThinkPHP是在中国使用极为广泛的PHP开发框架。在其版本5.0&#xff08;<5.1.23&#xff09;中,开启debug模式&#xff0c;传入的某参数在绑定编译指令的时候又没有安全处理&#xff0c;预编译的时候导致SQL异常报错。然而thinkphp5默认开启debug模式&#xff0c…

【代码问题】【Pytorch】训练模型时Loss为NaN或INF

解决方法或者问题排查&#xff1a; 加归一化层&#xff1a; 我的问题是我新增的一个模块与原来的模块得到的张量相加&#xff0c;原张量是归一化后的&#xff0c;我的没有&#xff1a; class Module(nn.Module):def __init__(self,dim,):super().__init__()# 新增一个LayerNo…

OpenAI发布GPT-4.0使用指南

大家好&#xff0c;ChatGPT 自诞生以来&#xff0c;凭借划时代的创新&#xff0c;被无数人一举送上生成式 AI 的神坛。在使用时&#xff0c;总是期望它能准确理解我们的意图&#xff0c;却时常发现其回答或创作并非百分之百贴合期待。这种落差可能源于我们对于模型性能的过高期…

ElasticSearch总结2

一、创建索引库&#xff1a;PUT ES中通过Restful请求操作索引库、文档。请求内容用DSL语句来表示。创建索引库和mapping的DSL语法如下&#xff1a; 整个jason 里边&#xff0c;它有一个叫mapping的属性&#xff0c;代表的是映射。映射里边有properties代表就是字段。可以看到这…

Android Studio入门级教程(详细)【小白必看】[通俗易懂]

Android Studio如何使用 本文主要讲解一下Android Studio使用方法 步骤&#xff1a; 1.建立项目 首先点击new——new project新建项目 选择想要创建的Android 的模板&#xff0c;建议选择empty activity&#xff08;空模板&#xff09;&#xff0c;然后next Name&#xff1…

(附源码)超级简单的SSM大学生创新创业管理系统,包含架构图、设计图、论文。

下面一大堆图和步骤看起来复杂&#xff0c;但是只要跟着教程走&#xff0c;都能部署成功。数据库设计简单明了&#xff0c;代码注释完整&#xff0c;小白也能看得懂&#xff0c;纯小白需要费点功夫。 项目结构图 内容截图&#xff1a; 用到软件 Jdk1.8 Mysql IntelliJ IDEA…

Python urllib 爬虫入门(1)

本文主要为Python urllib类库函数和属性介绍及一些简单示例。 目录 urllib爬取网页 简单示例 写入文件 其他读取方法 readline函数 readlines函数 response属性 当前环境信息 返回状态码 返回url地址 对url进行编码与解码 写入文件 总结 urllib爬取网页 通过pyth…

form1弹出子窗体form2,拖动子窗体判断是否离开父窗体区域,含源码(学习笔记)

一、效果&#xff08;进入和离开&#xff09; 子窗体到达父窗体边缘时变色。 二、代码分析 判断父窗体的目的&#xff0c;可以控制子窗体要随父窗体走。上面代码需要加以处理。 如&#xff1a;this.Location new Point(parentPoint.X distanceFromEdge, this.Location.Ydis…

NCC导入导出开发

&#x1f4e3;NCC导入导出开发 ✨1. 导入流程图 ✨2. 实现步骤 &#x1f434;1. 前端代码实现。 &#x1f434;2. 配置文件创建与设置。 &#x1f434;3. 后端代码实现。 &#x1f434;4. 注册后端代码类。

力扣---二叉树的右视图

给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4]示例 2: 输入: [1,null,3] 输出: [1,3]示例 3: 输入: [] 输出: []实现方法&…

双非本科自述: 无竞赛国奖,怎么逆袭腾讯字节

写在前面 大家好&#xff0c;我是青玉白露。 在这个充斥着精英主义色彩的社会里&#xff0c;"双一流"大学和耀眼奖项似乎成了走向职业成功、大厂的不二法门及必备之物。 然而&#xff0c;今天我要分享的&#xff0c;是一个打破常规的故事&#xff0c;是一个关于普…

AQS共享模式之CyclicBarrier

概念&#xff1a;CyclicBarrier翻译为循环(屏障/栅栏)&#xff0c;当一组线程到达一个屏障&#xff08;同步点&#xff09;时被阻塞&#xff0c;直到最后一个线程到达屏障时&#xff0c;屏障才会打开&#xff0c;所有被屏障拦截的线程才会继续工作。 设计目的&#xff1a;和Co…

什么牌子的洗地机质量比较好?四大热门品牌实测,快看过来

随着科技的发展&#xff0c;各种智能家居产品层出不穷&#xff0c;为我们的生活带来了诸多便利。近年来&#xff0c;在家庭清洁领域&#xff0c;洗地机成为了热门选择&#xff0c;可是什么牌子的洗地机质量比较好呢&#xff1f;我们一起来看看吧。 洗地机选购技巧&#xff1a;…

大数据中的项目数据采集

Datax介绍 官网&#xff1a; DataX/introduction.md at master alibaba/DataX GitHub DataX 是阿里云 DataWorks数据集成 的开源版本&#xff0c;在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。 DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS…

【漏洞复现】若依druid 未授权访问漏洞

0x01 产品简介 若依&#xff08;Ruoyi&#xff09;框架是一款基于Spring Boot、Spring Cloud、OAuth2与JWT鉴权等核心技术的快速开发平台。它支持多种安全框架和持久化框架&#xff0c;并采用前后端分离的模式进行开发&#xff0c;具备高度的灵活性和可扩展性。若依框架提供了…

VTK 的可视化方法:颜色映射

VTK 的可视化方法&#xff1a;颜色映射 VTK 的可视化方法&#xff1a;颜色映射颜色映射过程vtkDataSetvtkDataSetAttributesvtkLookUpTablevtkScalarBarActor实例参考 VTK 的可视化方法&#xff1a;颜色映射 颜色映射的操作对象是数据集中的标量属性。它是一种常用的标量算法。…

.net core ef 连表查询

Information和TypeInfo连表查询 类似&#xff1a; select st.Title1,si.* from [Star_Information] si left join Star_TypeInfo st on si.typeId2st.id 先在EfCoreDbContext.cs配置 protected override void OnModelCreating(ModelBuilder builder){base.OnModelCreating(b…

C++数据结构——二叉搜索树

二叉搜索树的概念 二叉树又称二叉排序树(BST&#xff0c;Binary Search Tree)&#xff0c;它是一颗空树&#xff0c;也可以是一颗具有下列性质的二叉树&#xff1a; 1.假如它的左子树不为空&#xff0c;那么左子树上的结点值都小于根结点的值。 2.假如它的右子树不为空&…

K8S controller编写之Informer的原理+使用[drift]

概念 核心思想&#xff08;重点&#xff09;watch-list 机制 Watch 通过 HTTP 协议与 Kubernetes API Server 建立长连接&#xff0c;接收 Kubernetes API Server 发来的资源变更事件。Watch 操作的实现机制使用 HTTP 协议的分块传输编码——当 client-go 调用 Kubernetes API…