基于 TCP 协议的并发服务器程序

2024-06-14 05:18

本文主要是介绍基于 TCP 协议的并发服务器程序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

服务端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <netdb.h>
#include <pthread.h>//线程执行函数,负责读写
void *thr_fn ( void *arg )
{int size, j;char recv_buf[1024];int *parg = ( int * ) arg;int new_fd = *parg;while ( ( size = read ( new_fd, recv_buf, sizeof ( recv_buf ) ) ) > 0 ) {if ( recv_buf[0] == '@' ) {break;}printf ( "Message from client(%d): %s\n", size, recv_buf );for ( j = 0; j < size; ++j )recv_buf[j] = toupper(recv_buf[j]);write(new_fd,recv_buf,size);}close(new_fd);return 0;
}int main(int argc, char *argv[]){socklen_t clt_addr_len;int listen_fd;int com_fd;int ret;int i;static char recv_buf[1024];int len;int port;pthread_t tid;struct sockaddr_in clt_addr;struct sockaddr_in srv_addr;//服务器端运行时要给出端口信息,该端口为监听端口if(argc != 2){printf("Usage:%s port\n",argv[0]);return -1;}//获得输入的端口port = atoi(argv[1]);//创建套接字用于服务器的监听listen_fd = socket(PF_INET,SOCK_STREAM,0);if(listen_fd < 0){perror("cannot create listening socket");return -1;}//填充关于服务器的套接字信息memset(&srv_addr,0,sizeof(srv_addr));srv_addr.sin_family = AF_INET;srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);srv_addr.sin_port = htons(port);//将服务器和套接字绑定ret = bind(listen_fd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));if(ret == -1){perror("cannot bind server socket");close(listen_fd);return -1;}//监听指定端口ret = listen(listen_fd,5);if(ret == -1){perror("cannot listen the client connect request");close(listen_fd);return -1;}/*对每个连接来的客户端创建一个线程,单独与其进行通信,首先调用 read 函数读取客户端发送来的信息将其转化成大写后发送回客户端当输入"@"时,程序退出*/while(1){len = sizeof(clt_addr);com_fd = accept(listen_fd,(struct sockaddr *)&clt_addr,&len);if(com_fd < 0){if(errno == EINTR)continue;else{perror("cannot accept client connect request");close(listen_fd);return -1;}}printf("com_fd = %d\n",com_fd); //打印建立连接的客户端产生的套接字if((pthread_create(&tid,NULL,thr_fn,&com_fd)) == -1){perror("pthread_create error");close(listen_fd);close(com_fd);return -1;}}return 0;
}

客户端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <unistd.h>int main(int argc, char**argv){int connect_fd;int ret;char snd_buf[1024];int i;int port;int len;static struct sockaddr_in srv_addr;//客户端运行需要给出具体的连接地址和端口if(argc != 3){printf("Usage: %s server_ip_address port\n",argv[0]);return -1;}//获得输入的端口port = atoi(argv[2]);//创建套接字用于客户端的连接connect_fd = socket(PF_INET,SOCK_STREAM,0);if(connect_fd < 0){perror("cannot create communication socket");return 1;}//填充关于服务器的套接字信息memset(&srv_addr,0,sizeof(srv_addr));srv_addr.sin_family = AF_INET;srv_addr.sin_addr.s_addr = inet_addr(argv[1]);srv_addr.sin_port = htons(port);//连接指定的服务器ret = connect(connect_fd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));if(ret == -1){perror("cannot connect to the server");close(connect_fd);return -1;}memset(snd_buf,0,1024);/*用户输入信息后,程序将输入的信息通过套接字发送给服务器,然后调用read函数从服务器中读取发送来的信息当输入"@"时,程序退出*/while(1){write(STDOUT_FILENO,"input message:", 14);len = read(STDIN_FILENO,snd_buf,1024);if(len > 0)write(connect_fd,snd_buf,len);len = read(connect_fd,snd_buf,len);if(len > 0)printf("Message form server: %s\n",snd_buf);if(snd_buf[0] == '@')break;}close(connect_fd);return 0;
}



这篇关于基于 TCP 协议的并发服务器程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1059482

相关文章

高并发环境中保持幂等性

在高并发环境中保持幂等性是一项重要的挑战。幂等性指的是无论操作执行多少次,其效果都是相同的。确保操作的幂等性可以避免重复执行带来的副作用。以下是一些保持幂等性的常用方法: 唯一标识符: 请求唯一标识:在每次请求中引入唯一标识符(如 UUID 或者生成的唯一 ID),在处理请求时,系统可以检查这个标识符是否已经处理过,如果是,则忽略重复请求。幂等键(Idempotency Key):客户端在每次

【Linux】应用层http协议

一、HTTP协议 1.1 简要介绍一下HTTP        我们在网络的应用层中可以自己定义协议,但是,已经有大佬定义了一些现成的,非常好用的应用层协议,供我们直接使用,HTTP(超文本传输协议)就是其中之一。        在互联网世界中,HTTP(超文本传输协议)是一个至关重要的协议,他定义了客户端(如浏览器)与服务器之间如何进行通信,以交换或者传输超文本(比如HTML文档)。

Java并发编程之——BlockingQueue(队列)

一、什么是BlockingQueue BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: 1. 当队列满了的时候进行入队列操作2. 当队列空了的时候进行出队列操作123 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空

【Go】go连接clickhouse使用TCP协议

离开你是傻是对是错 是看破是软弱 这结果是爱是恨或者是什么 如果是种解脱 怎么会还有眷恋在我心窝 那么爱你为什么                      🎵 黄品源/莫文蔚《那么爱你为什么》 package mainimport ("context""fmt""log""time""github.com/ClickHouse/clickhouse-go/v2")func main(

2024.9.8 TCP/IP协议学习笔记

1.所谓的层就是数据交换的深度,电脑点对点就是单层,物理层,加上集线器还是物理层,加上交换机就变成链路层了,有地址表,路由器就到了第三层网络层,每个端口都有一个mac地址 2.A 给 C 发数据包,怎么知道是否要通过路由器转发呢?答案:子网 3.将源 IP 与目的 IP 分别同这个子网掩码进行与运算****,相等则是在一个子网,不相等就是在不同子网 4.A 如何知道,哪个设备是路由器?答案:在 A

图解TCP三次握手|深度解析|为什么是三次

写在前面 这篇文章我们来讲解析 TCP三次握手。 TCP 报文段 传输控制块TCB:存储了每一个连接中的一些重要信息。比如TCP连接表,指向发送和接收缓冲的指针,指向重传队列的指针,当前的发送和接收序列等等。 我们再来看一下TCP报文段的组成结构 TCP 三次握手 过程 假设有一台客户端,B有一台服务器。最初两端的TCP进程都是处于CLOSED关闭状态,客户端A打开链接,服务器端

java线程深度解析(五)——并发模型(生产者-消费者)

http://blog.csdn.net/Daybreak1209/article/details/51378055 三、生产者-消费者模式     在经典的多线程模式中,生产者-消费者为多线程间协作提供了良好的解决方案。基本原理是两类线程,即若干个生产者和若干个消费者,生产者负责提交用户请求任务(到内存缓冲区),消费者线程负责处理任务(从内存缓冲区中取任务进行处理),两类线程之

java线程深度解析(四)——并发模型(Master-Worker)

http://blog.csdn.net/daybreak1209/article/details/51372929 二、Master-worker ——分而治之      Master-worker常用的并行模式之一,核心思想是由两个进程协作工作,master负责接收和分配任务,worker负责处理任务,并把处理结果返回给Master进程,由Master进行汇总,返回给客

Modbus-RTU协议

一、协议概述 Modbus-RTU(Remote Terminal Unit)是一种基于主从架构的通信协议,采用二进制数据表示,消息中的每个8位字节含有两个4位十六进制字符。它主要通过RS-485、RS-232、RS-422等物理接口实现数据的传输,传输距离远、抗干扰能力强、通信效率高。 二、报文结构 一个标准的Modbus-RTU报文通常包含以下部分: 地址域:单个字节,表示从站设备

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理 秒杀系统是应对高并发、高压力下的典型业务场景,涉及到并发控制、库存管理、事务管理等多个关键技术点。本文将深入剖析秒杀商品业务中常见的几个核心问题,包括 AOP 事务管理、同步锁机制、乐观锁、CAS 操作,以及用户限购策略。通过这些技术的结合,确保秒杀系统在高并发场景下的稳定性和一致性。 1. AOP 代理对象与事务管理 在秒杀商品