当前位置: 首页 > news >正文

LINUX网络编程(TCP)(3)

为什么80%的码农都做不了架构师?>>>   hot3.png

上一篇中说到了第一种方法,Fork,

这里在使用另一种方法:thread (线程)。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <pthread.h>

#define PORT_NUM	(2227)		//定义端口号。
#define BUFFSIZE	(1024)

#define	CMD_ONE			("1")
#define CMD_TWO			("2")
#define CMD_THREE		("3")

#define CMD_CODE_ERR	(0)
#define CMD_CODE_ONE	(1)
#define CMD_CODE_TWO	(2)
#define CMD_CODE_THREE	(3)

#define LISTEN_QUE		(10)

#define LOG_MSG(format, ...)	do{fprintf(stderr, "[MessageInfo]: "format" \n", ##__VA_ARGS__);}while(0)

typedef struct socklnk_st{
	int32_t sd;
	struct socklnk_st *next;
}socklnk_t;


socklnk_t*
create_soclnk(int32_t data)
{
	socklnk_t *soclnk = NULL;
	
	soclnk = (socklnk_t *)malloc(sizeof(socklnk_t));
	if(soclnk != NULL){
		soclnk->next = NULL;
		soclnk->sd = data;
	}
	
	return soclnk;
}

void
free_soclnk(socklnk_t *dst)
{
	socklnk_t *tmp = dst;
	socklnk_t *next;

	while(tmp != NULL){
		next = tmp->next;
		close(tmp->sd);
		free(tmp);
		tmp = next;
	}
}

//定义每个Code返回值。
static int8_t *server_msg[] = {
	[CMD_CODE_ONE] = "Hello",
	[CMD_CODE_TWO] = "Good",
	[CMD_CODE_THREE] = "Bye",
	[CMD_CODE_ERR]	= "Error Command",
};

socklnk_t *
start_serice(uint16_t port)
{
	int8_t serv[NI_MAXSERV];
	int32_t sd;
	int32_t opt = 1;
	struct addrinfo *ai, *res = NULL;
	struct addrinfo hints;
	socklnk_t *head = NULL;
	socklnk_t *cur  = NULL;	
	
	if(snprintf(serv, NI_MAXSERV, "%u", port) < 0){
		goto func_end;
	}
	
	(void)memset(&hints, 0x00, sizeof hints);
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;
	
	if(getaddrinfo(NULL, serv, &hints, &res) != 0){
		goto func_end;
	}
	
	for(ai = res; ai != NULL; ai = ai->ai_next){
		sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if(sd < 0){
			continue;
		}
		
		if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt) < 0){
			close(sd);
			free_soclnk(head);
			goto func_end;
		}
		
		if(bind(sd, ai->ai_addr, ai->ai_addrlen) < 0){
			close(sd);
			continue;
		}
		
		if(listen(sd, LISTEN_QUE) < 0){
			close(sd);
			continue;
		}
		
		if(head == NULL){
			head = create_soclnk(sd);
			if(head == NULL){
				close(sd);
				free_soclnk(head);
				goto func_end;			
			}
			cur = head;
		}else{
			cur->next = create_soclnk(sd);
			if(cur->next == NULL){
				close(sd);
				free_soclnk(head);
				goto func_end;			
			}
			cur = cur->next;
		}
	}
	
func_end:
	if(res != NULL){
		freeaddrinfo(res);
	}

	return head;
}



void *
func_proc(void *arg)
{
	int8_t *buf;
	int32_t ret = -1;
	int32_t *sd;
	int32_t cmd;
	int32_t sendlen;
	int32_t connfd;
	
	buf = (int8_t*)malloc(BUFFSIZE);
	if(buf == NULL){
		LOG_MSG("Service Process Failed");
		goto func_end;		
	}
	
	if(arg == NULL){
		LOG_MSG("Service Process Failed");
		goto func_end;		
	}
	
	sd = (int32_t *)arg;
	connfd = *sd;

	for(;;){
		(void)memset(buf, 0x00, BUFFSIZE);
		
		if(read(connfd, buf, BUFFSIZE) > 0){
			if(strncmp(buf, CMD_ONE, strlen(CMD_ONE)) == 0){
				cmd = CMD_CODE_ONE;
			}else if(strncmp(buf, CMD_TWO, strlen(CMD_TWO)) == 0){
				cmd = CMD_CODE_TWO;
			}else if(strncmp(buf, CMD_THREE, strlen(CMD_THREE)) == 0){
				cmd = CMD_CODE_THREE;
			}else{
				cmd = CMD_CODE_ERR;
			}

			sendlen = strlen(server_msg[cmd]);
			
			if(write(connfd, server_msg[cmd], sendlen) != sendlen){
				close(connfd);			
				goto func_end;
			}
				
			if(cmd == CMD_CODE_THREE){
				break;
			}
		}else{
			break;
		}
	}
	
func_end:
	if(buf != NULL){
		free(buf);
	}
	
	close(connfd);
	
	pthread_exit(NULL);

}

int
main(int ac, char **av)
{
	
	int32_t connfd;
	int32_t maxfd = -1;
	
	
	fd_set fds;
	pthread_t tid[10];
	
	socklnk_t *sdlnk = NULL;
	socklnk_t *this;
	
	sdlnk = start_serice(PORT_NUM);
	if(sdlnk == NULL){
		LOG_MSG("Service Start Failed");
		goto func_end;
	}

	//main Loops
	for(;;){
		FD_ZERO(&fds);
		for(this = sdlnk; this != NULL; this = this->next){
			FD_SET(this->sd, &fds);
			if(this->sd > maxfd){
				maxfd = this->sd;
			}
		}
		
		if(select(maxfd + 1, &fds, NULL, NULL, NULL) > 0){
			for(this = sdlnk; this != NULL; this = this->next){
				if(FD_ISSET(this->sd, &fds) != 0){
					if((connfd = accept(this->sd, NULL, NULL)) < 0){
						continue;
					}
					break;
				}
			}
		}else{
			goto func_end;
		}
	
		if(this == NULL){
			goto func_end;
		}
		
		if(pthread_create(&tid, NULL, func_proc, &connfd) != 0){
			LOG_MSG("Service Process Failed");
			close(connfd);
			goto func_end;
		}
	
	}	
	
func_end:
	if(sdlnk != NULL){
		free_soclnk(sdlnk);
	}
	
	return 0;
}


转载于:https://my.oschina.net/hjxc/blog/278488

相关文章:

  • 项目私活 【抢小米手机软件】能够做的朋友,能够联系社区
  • 二进制文件和ASCII文件有何差别
  • 实战6 Nginx的web日志导入到MongoDB数据库
  • dell c1100 安装系统(进入bios、超线程、磁盘阵列等设置方法)
  • FineUI小技巧(1)简单的购物车页面
  • 关于腾讯QQ登录提示“个人文件夹没有读写权限,请修改相应权限后再尝试”的解决方法...
  • 第三节 改变字符串的值
  • 再读《精通css》00
  • [转]个数为n的只读数组包含元素[1, n-1],求其中一个重复的数
  • 韩立刚老师51cto课程学习路线图
  • C#如何判断两个数组相等
  • 如何vs升级后10和12都能同时兼容
  • 应用wordpress
  • 使用 EF Power Tool Code Frist 生成 Mysql 实体
  • 【LeetCode】37. Sudoku Solver
  • Apache Spark Streaming 使用实例
  • C++类中的特殊成员函数
  • CentOS从零开始部署Nodejs项目
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Java|序列化异常StreamCorruptedException的解决方法
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Mybatis初体验
  • mysql innodb 索引使用指南
  • ReactNativeweexDeviceOne对比
  • spring boot下thymeleaf全局静态变量配置
  • Vue组件定义
  • 基于组件的设计工作流与界面抽象
  • 浅谈Golang中select的用法
  • 一道面试题引发的“血案”
  • (13)Hive调优——动态分区导致的小文件问题
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (26)4.7 字符函数和字符串函数
  • (8)STL算法之替换
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (三)uboot源码分析
  • (转) ns2/nam与nam实现相关的文件
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .net wcf memory gates checking failed
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .Net环境下的缓存技术介绍
  • .net网站发布-允许更新此预编译站点
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • @ModelAttribute注解使用
  • [ vulhub漏洞复现篇 ] Apache APISIX 默认密钥漏洞 CVE-2020-13945
  • [20171102]视图v$session中process字段含义
  • [2024最新教程]地表最强AGI:Claude 3注册账号/登录账号/访问方法,小白教程包教包会
  • [30期] 我的学习方法
  • [Android]常见的数据传递方式
  • [Android]通过PhoneLookup读取所有电话号码
  • [BT]BUUCTF刷题第4天(3.22)
  • [BZOJ] 2427: [HAOI2010]软件安装
  • [BZOJ1089][SCOI2003]严格n元树(递推+高精度)
  • [BZOJ3223]文艺平衡树