linux网络编程-简单多线程并发服务器实现

pthread_create()简要介绍

pthread_create()函数是创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。 pthread_create的返回值表示成功,返回0;表示出错,返回表示-1。

在这里插入图片描述

pthread_detach()简要介绍

int pthread_detach(pthread_t thread); 成功:0;失败:错误号
作用:从状态上实现线程分离
线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后(不会产生僵尸线程),其退出状态不由其他线程获取,而直接自己自动释放(自己清理掉PCB的残留资源)。网络、多线程服务器常用。

代码分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
pthread非linux系统的默认库, 需手动链接-线程库 -lpthread

gcc server.c wrap.c -o server -lpthread

“undefined reference to”的意思是,该函数未定义。
如果提示未定义的函数是某个库的函数。检查库时候已经安装,并在编译命令中采用-l和-L参数导入库。
如果提示未定义的函数是程序中的函数。检查是否在头文件中声明,是否在编译中有对应的obj文件。
如果提示未定义的函数是程序中的函数,还有一种很隐蔽的可能:检查改函数的代码的上下文是否有#ifdef或者#ifndef等预编译信息,这也很有可能导致相关代码没有被编译而出现“undefined reference to”提示。

在这里插入图片描述

代码

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>

#include "wrap.h"

struct client_info{
	struct sockaddr_in cliaddr;
	int connfd;
};


//线程执行的工作
void *do_work(void *arg)
{
  struct client_info *ts = (struct client_info*)arg;


  while(1){
    char buf[1024];
    int n = Read(ts->connfd,buf,1024);
    
   //如果接收到的数据长度为0 那么就是已经结束了
    if(n==0) {
      printf("the client %d closed....\n", ts->connfd);
      break;
    }
   //打印客户端信息
   char str[INET_ADDRSTRLEN];
   printf("received from %s at port %d\n",
           inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)),
	   ntohs((*ts).cliaddr.sin_port));
   //转换大小写
   int i;
    for (i = 0; i < n; i++) 
            buf[i] = toupper(buf[i]);                           //小写-->大写
   //写数据
        Write(STDOUT_FILENO, buf, n);                           //写出至屏幕
        Write(ts->connfd, buf, n);                              //回写给客户端
 
 }
 Close(ts->connfd);
 return (void *)0;

}



int main(void)
{	
 	//创建一个监听socket
	int listenfd= Socket(AF_INET,SOCK_STREAM,0);
	
	//建立并绑定监听地址
	struct sockaddr_in servaddr;
	bzero(&servaddr,sizeof(servaddr));
 	servaddr.sin_family=AF_INET;
	servaddr.sin_port=htons(7000);
	servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
        Bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
 
	//设置监听个数
	Listen(listenfd,20);
	
	printf("accepting client connect....\n");
	
	//创建一个用于保存客户端数据的结构体
	struct client_info cinfo[256];
	int i=0;
	pthread_t tid;//线程
        
	while(1){
		//创建一个用于接收客户地址的sockaddr_in
		 struct sockaddr_in cliddr;
		 socklen_t cliaddr_len = sizeof(cliddr);

 		 //返回连接的文件描述符
        	 int connfd = Accept(listenfd,(struct sockaddr *)&cliddr,&cliaddr_len);
	 
		//将信息都保存到结构体数组中        
 		cinfo[i].cliaddr=cliddr;
		cinfo[i].connfd=connfd;
		pthread_create(&tid, NULL, do_work, (void*)&cinfo[i]);
        pthread_detach(tid);  
		i++;
	}	

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贪睡的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值