Chinaunix首页 | 论坛 | 博客
  • 博客访问: 252081
  • 博文数量: 101
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 95
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-12 12:35
文章分类

全部博文(101)

文章存档

2016年(5)

2015年(16)

2014年(37)

2013年(32)

2012年(8)

2011年(3)

我的朋友

分类: C/C++

2014-09-19 09:52:27

原文地址:socket c/s程序 作者:青竹玉简

//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) |
给主人留下些什么吧!~~