标签:socket thread 编程 server client 线程 pthread fd 多线程
1.多线程基础知识
线程是进程的一条执行路径,线程在Unix系统下,通常被称为轻量级的进程。所有的线程都是在同一进程空间运行,这也意味着多条线程将共享该进程中的全部系统资 源,如虚拟地址空间,文件描述符和信号处理等等。一个进程可以有很多线程,每条线程并行执行不同的任 务。
一个进程创建后,会首先生成一个缺省的线程,通常称这个线程为主线程(或称控制线程)。主线程就是通过main函数进入的线程,由主线程调用pthread_create()创建的线程称为子线程。
主线程和子线程的默认关系是:无论子线程执行完毕与否,一旦主线程执行完毕退出,所有 子线程执行都会终止。
主线程和子线程通常定义以下两种关系:
可会合:这种关系下,主线程需要明确执行等待操作,在子线程结束后,主线程的等待操作执行完毕,子线 程和主线程会合,这时主线程继续执行等待操作之后的下一步操作。主线程必须会合可会合的子线程。在主线程的线程函 数内部调用子线程对象的wait函数实现,即使子线程能够在主线程之前执行完毕,进入终止态,也必须执行会合操作,否 则,系统永远不会主动销毁线程,分配给该线程的系统资源也永远不会释放。
相分离:表示子线程无需和主线程会合,也就是相分离的,这种情况下,子线程一旦进入终止状态,这种 方式常用在线程数较多的情况下,有时让主线程逐个等待子线程结束,或者让主线程安排每个子线程结束的等待顺序,是 很困难或不可能的,所以在并发子线程较多的情况下,这种方式也会经常使用。
线程的分离状态决定一个线程以什么样的方式来终止自己,在默认的情况下,线程是非分离状态的,这种情况下,原有的线程 等待创建的线程结束,只有当pthread_join()函数返回时,创建的线程才算终止,释放自己占用的系统资源,而分离线程没有被其 他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。
2.实现函数
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
typedef struct
{
int detachstate; //线程的分离状态
int schedpolicy; //线程调度策略
struct sched_param schedparam; //线程的调度参数
int inheritsched; //线程的继承性
int scope; //线程的作用域
size_t guardsize; //线程栈末尾的警戒缓冲区大小
int stackaddr_set;
void * stackaddr; //线程栈的位置
size_t stacksize; //线程栈的大小
}pthread_attr_t;
3.实现代码
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <getopt.h>
#include <pthread.h>
#include <ctype.h>
#define MSG_STR "Hello, you have connected to the server successfully!\n"
typedef void *(THREAD_BODY)(void *thread_arg);
void *thread_worker(void *ctx);
int thread_start(pthread_t *thread_id, THREAD_BODY *thread_workbody, void *thread_arg);
void *thread_worker(void *ctx)
{
int client_fd;
int rv;
char buf[1024];
int i;
if( !ctx )
{
printf("ERROR: invalid input argments!\n");
pthread_exit(NULL);
}
client_fd = (int)ctx;
while(1)
{
memset(buf, 0, sizeof(buf));
rv=read(client_fd, buf, sizeof(buf));
if( rv < 0)
{
printf("Read data from client[%d] unsuccessfully: %s and thread will exit\n", client_fd, strerror(errno));
close(client_fd);
pthread_exit(NULL);
}
else if( rv == 0)
{
printf("Socket[%d] get disconnected and thread will exit.\n", client_fd); close(client_fd);
pthread_exit(NULL);
}
else if( rv > 0 )
{
printf("Read %d bytes data from Server: %s\n", rv, buf);
}
rv=write(client_fd, MSG_STR, strlen(MSG_STR));
if(rv < 0)
{
printf("Write to client by sockfd[%d] failure: %s and thread will exit\n", client_fd, strerror(errno));
close(client_fd);
pthread_exit(NULL);
}
}
}
int thread_start(pthread_t *thread_id, THREAD_BODY *thread_workbody, void *thread_arg)
{
pthread_attr_t thread_attr;
if( pthread_attr_init(&thread_attr) )
{
printf("pthread_attr_init() failure: %s\n", strerror(errno));
return -1;
}
if( pthread_attr_setstacksize(&thread_attr, 120*1024) )
{
printf("pthread_attr_setstacksize() failure: %s\n", strerror(errno));
return -2;
}
if( pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) )
{
printf("pthread_attr_setdetachstate() failure: %s\n", strerror(errno));
return -3;
}
if( pthread_create(thread_id, &thread_attr, thread_workbody, thread_arg) )
{
printf("Create thread failure: %s\n", strerror(errno));
return -4;
}
return 0;
}
int main(int argc, char **argv)
{
int server_fd = -1, client_fd = -1;
int rv = -1;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t len;
int port = 8889;
int on = 1;
pthread_t tid;
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if(server_fd < 0)
{
printf("Create socket unsuccessfully: %s\n", strerror(errno));
return -1;
}
printf("Create socket[%d] successfully!\n", server_fd);
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
rv=bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(rv < 0)
{
printf("Socket[%d] bind on port[%d] failure: %s\n", server_fd, port, strerror(errno));
return -2;
}
listen(server_fd, 10);
while(1)
{
client_fd=accept(server_fd, (struct sockaddr *)&client_addr, &len);
if(client_fd < 0)
{
printf("Accept new client failure: %s\n", strerror(errno));
continue;
}
printf("Accept new client[%s:%d] successfully\n\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
thread_start(&tid, thread_worker, (void *)client_fd);
}
close(server_fd);
return 0;
}
马脸老头
发布了3 篇原创文章 · 获赞 0 · 访问量 41
私信
关注
标签:socket,thread,编程,server,client,线程,pthread,fd,多线程 来源: https://blog.csdn.net/qq_42645327/article/details/103979548
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。