网络编程实验3-并发多线程服务器设计
实验目的
本次实验的主要目的是使用多线程实现并发的,面向连接的服务器设计。
实验内容
1、设计多线程的,面向连接的并发服务器
2、改造客户端为面向连接的多线程客户端
基本概念
1、将线程用于并发的、面向连接服务器的算法
主1 创建套接字并将其绑定到所提供服务的熟知地址上。让该套接字保持非连接。
主2 将该端口设置为被动模式,使其准备为服务器所用。
主3 反复调用accept以便接受来自客户的下一个连接请求,并创建新的从线程来处理响应。
从1 由主线程传递来的连接请求(即针对连接的套接字)开始。
从2 用该连接与客户进行交互:读取请求并发回响应。
从3 关闭连接并退出。在处理完来自客户的所有请求后,从线程就退出。
2、线程
线程是一个进程内部的一个控制序列,是一次独立的计算。
(1)创建线程
#include <pthread.h>
int pthread_create(pthread_t thread, pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg);
返回值: 0 成功 错误号表示失败。
thread: 指向pthread_t类型的变量,新创建的线程标识符;
attr:指向pthread_attr_t线程属性类型的变量,
start_routine: 指向线程函数的指针,线程要执行的代码。
arg: 指向线程参数的指针。
(2)终止线程
线程退出方式:
① 从线程函数中返回,返回值为线程的退出码;
return(retu_val);
② 被同一进程的其他线程终止,即被取消;
pthread_cancel;
③ 执行线程退出调用;
pthread_exit;
exit
线程退出:
#include <pthread.h>
void pthread_exit(void *retval);
*retval: void类型的指针。
线程终止:
#include <pthread.h>
int pthread_cancel(pthread_t th);
返回值: 0 成功 错误号表示失败
(3)等待线程
等待线程的终止。
#include <pthread.h>
int pthread_join(pthread_t th, void **thread_return);
返回值:0 成功 错误码表示失败
(4)线程协调和同步
Linux的同步机制:
① 互斥( mutex)
② 信号量( semaphore)
③ 条件变量( condition variable)
(5)线程的属性
属性: 脱离线程(detached thread)
初始化属性对象
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
返回码:成功 0
失败 错误代码
回收函数
Pthread_attr_destroy(pthread_attr_t *attr);
实验步骤
1.编写头文件sockutil.h
#ifndef SOCKUTIL_H
#define SOCKUTIL_H
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<netdb.h>
#ifndef INADDR_NONE
#define INADDR_NONE 0xFFFFFFFF
#endif
int connectSock(char* host,char* service,char* protocol);
int passiveSock(char* service,char* protocol,int qlen);
void errexit(char* fmt,...);
#endif
2.创建sockutil.c文件,编写通用过程connectSock及passiveSock代码
#include "sockutil.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
int connectSock(char* host,char* service,char* protocol)
{
struct hostent* pHost;
struct servent* pServ;
struct protoent* pProto;
struct sockaddr_in addr;
int s,type;
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
if((pHost=gethostbyname(host))!=NULL)
memcpy(&addr.sin_addr,pHost->h_