//gcc client.c -o client -lpthread 执行命令
/*客户端程序实现与服务器链接,同时接受服务器信息*/
#include
#include
#include
#include
#include
#include
#include
#include //线程头文件
#define MAXSIZE 200 //宏声明并定义MAXSIZE = 200
void *doitA(void *); //声明指针函数
/*
*定义指针函数作为线程的调用函数,实现读功能。
*/
void *doitA(void *sockfd)
{
int count, str_read;
char sbuf[MAXSIZE];
count = *((int *) sockfd);
/*
*声明整形变量count,并将*sockfd转换成整形赋值给count,声明整形变量str_read;
*声明字符数组sbuf,最大值为MAXSIZE。
*/
while (1)
{
str_read = read(count, sbuf, MAXSIZE); //把read的返回值赋值给str_read。
if (str_read < 0 || str_read == 0)
{
perror("read"); //小于等于零时的read函数的错误输出。
exit(1); //异常退出。
}
printf("从服务器进程收到的信息(离开请您输入X):\n%s",sbuf); //打印数组sbuf中的字符。
}
}
int main(int argc, char *argv[])
{
int len, sockfd;
pthread_t tidA;
struct sockaddr_in address;
char buf[MAXSIZE], sbuf[MAXSIZE];
/*定义整形变量len,作为sizeof(address)的返回值,定义整形变量sockfd;作为 *\
*sockfd返回值。定义sockaddr类型的结构体address。定义字符输出 buf[MAXSIZE],*
\* sbuf[MAXSIZE];长度为MAXSIZE。 */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket"); //调用函数socket并把返回值赋值给sockfd,等于零时的socker函数的错误输出。
exit(1); //异常退出。
}
bzero(&address, sizeof(address)); //将结构体清零。
address.sin_family = AF_INET; //设定协议族
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //设定ip地址
address.sin_port = htons(5000); //设定端口5000
len = sizeof(address); //把address结构体长度赋值给len
//向服务器发出链接请求,并判断相应的返回值,作响应的处理。
if (connect(sockfd, (struct sockaddr *) &address, len) == -1)
{
perror("connect");
exit(1);
}
/*打印姓名,获得键盘输入,并存入buf数组,“将加入聊天室\n”和buf中的字符链接在一起,
*并且存入buf数组,再把数组内容写入sockfd。 */
printf("请输姓名:");
fgets(buf, MAXSIZE, stdin);
strcat(buf, "加入聊天室\n");
write(sockfd, buf, MAXSIZE);
while (1) //设置死循环。
{
memset(buf, 0, MAXSIZE); //buf清零。
memset(sbuf, 0, MAXSIZE); //sbuf清零。
pthread_create(&tidA, NULL, &doitA, &sockfd); //创建线程,调用doit,实现读的独立。
/*判断键盘的输入,如果为X,退出*/
fgets(buf, MAXSIZE, stdin); //输入存入buf数组。
memcpy(sbuf, buf, 1); //把buf中的第一个字符输出到sbuf数组中。
if (strcmp(sbuf, "X") == 0) //sbuf中的字符与X对比。
{
close(sockfd); //关闭sockfd。
printf("客户端正常退出,感谢您的使用。\n");
return 0;
}
//判断输入为空,打印消息,同时再次循环。
if (buf[0] == '\n')
{
printf("输入不能为空,请输入有效内容。\n");
continue;
}
write(sockfd, buf, MAXSIZE); //写入sockfd。
}
exit(0); //安全退出。
}
//gcc server.c -o server -lpthread //执行命令。
/*客户端程序实现接受多客户机的请求,并实现多线程广播功能*/
#include
#include
#include
#include
#include
#include
#include
#include //线程头文件。
#define MAXSIZE 200
/*
*指针函数的声明;
*声明全局整形数组sockset,设定长度为一百。
*声明全局整形变量,并赋值为0。
*对锁counter_mutex初始化。
*/
void *doitA(void *);
int sockset[100];
int n = 0;
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
/*对sockset数组初始化为-1。*/
int initial_arry()
{
int i;
for (i = 0; i < 100; i++)
{
sockset[i] = -1;
}
}
/*线程函数实现读和广播*/
void *doitA(void *client_sockfd)
{
char sbuf[MAXSIZE], cbuf[MAXSIZE];
int trans_sockfd; //声明整形变量count。
int j = 0, str_read;
trans_sockfd = *((int *) client_sockfd); //将*sockfd转换成整形赋值给trans_sockfd。
while (1)
{
str_read = read(trans_sockfd, cbuf, MAXSIZE); //把read的返回值赋值给str_read。
if (str_read < 0 || str_read == 0)
{
//perror("read"); 错误输出。
exit(1); //异常退出。
}
printf("收到客户进程的信息:%s\n", cbuf); //打印cbuf数组中的字符。
strcpy(sbuf, "服务器进程收到您的信息:"); //把字符串"服务器进程收到您的信息:"写入sbuf数组。
strcat(sbuf, cbuf); //把cbuf数组的字符链接在sbuf字符之后。并返回指向sbuf。
/*使用锁保证广播的原子行*/
pthread_mutex_lock(&counter_mutex); //加锁。
for (j = 0; j < n; j++)
{
write(sockset[j], sbuf, MAXSIZE); //将sbuf数组放入sockset每一项。
}
pthread_mutex_unlock(&counter_mutex); //解锁。
}
}
int main()
{
int i = 0;
pthread_t tidA;
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
/*定义变量i,赋值为0;定义线程号tidA;定义整形量server_sockfd、client_sockfd
* server_len、client_len;分别表示socket的返回值,accept的返回值,结构体长度
*的返回值,作为accept的参数。
*/
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&server_address, sizeof(server_address)); //将结构体清零。
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = htons(5000); //设定端口5000。
server_len = sizeof(server_address); //把server_address结构体长度赋值给len。
bind(server_sockfd, (struct sockaddr *) &server_address, server_len); //服务器与客户端绑定。
listen(server_sockfd, 6); //设定最多监听数目为6。
initial_arry(); //调用初始化函数,也可以用memset初始化。
/*while循环实现client_sockfd在数组中的存储,同时创建线程。*/
while (1)
{
printf("服务器进程在等待客户进程的连接:\n");
client_sockfd =accept(server_sockfd, (struct sockaddr *) &client_address,&client_len);
printf("客户端已登录。\n");
/*实现client_sockfd在数组中的存储*/
if (client_sockfd != -1)
{
pthread_mutex_lock(&counter_mutex);
sockset[i] = client_sockfd;
i++;
n = i;
pthread_mutex_unlock(&counter_mutex);
pthread_create(&tidA, NULL, doitA, &client_sockfd); //创建线程。
}
}
exit(0); //安全退出。
}
阅读(766) | 评论(0) | 转发(0) |