简单的网络编程.

1219阅读 0评论2010-11-29 lthyxy
分类:

有进步了,实现了服务器可以向每个客户端发送一样的信息。
下次要解决,不同的客户端之间的通信以及服务器向不同的客户端通信.

//已经可以通过服务器向每个客户端发送消息了

//客户端输入quit就会退出连接。并且服务器相应的线程也会终止。

————————————————————————服务器————————————————
#include <cstdio>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <string>
#include <iostream>
#include <pthread.h>
#include <unistd.h>//fork,getpid

#include <time.h>
using namespace std;

int fd[100];//建立的套字接描诉符号。

int haha = 1;//每个套字接描诉符号对应的下标


void* thread(void* s)
{
  int len = 1;
  char buf[BUFSIZ];
   time_t rawtime;
   struct tm * timeinfo;
   int heihei = haha-1;//记录下此接上客户端的套字接描诉符号

  while((len = recv(fd[heihei],buf,BUFSIZ,0)) > 0)
  {
   if(buf[11] == 'q' && buf[12] == 'u' && buf[13] == 'i' && buf[14] == 't' && buf[15] == '\n') break;//如果客户端输入quit就退出此接收数据

   buf[len-1] = '\0';
   string c(buf,buf+len);
   string b;
   b += c;
   time ( &rawtime );
   timeinfo = localtime ( &rawtime ); //获得本地系统时间。

   printf("(ID:%d) %d:%d:%d\n%s\n",fd[heihei],timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec,b.data());
  }
 send(fd[heihei],"you have quited lthyxy's server!\n",35,0);//告诉客户端已经离开了

 fd[heihei] = 0;//把他变0,防止等下向每个客户端送数据时出现问题

  printf("client (ID:%d) at %d:%d:%d quite the server....\n",fd[heihei],timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
 return s;
}

void* threadd(void *s)
{
    int len;
    string zhuji("lthyxy(system):");
    while(1)//死循环,不停的向客户端发的信息,暂时还只可以通过控制台向第一个客户端.

    {
     char buff[BUFSIZ];
               string k1;
               string k2(zhuji);
        while(getline(cin,k1)){ k2 += k1;}//感觉处理没C++的方便就偷懒了一下,呵呵。

        cin.clear();
        len = k2.size();
        strcpy(buff,k2.c_str());
        buff[len] = '\n';
                for(int hj = 1; hj < haha; ++hj)
        if(fd[hj] && send(fd[hj], buff, len+1, 0) < 0)//再发回给客户端.

        {
         perror("write!");
         return (void*)1;
         }
    }
return s;
}

int main()//主函数创建一个向每个客户端输送数据的线程后就进入死循环不停的accept,一旦接收就创建一个线程去与之对应接受数据

{
     int s;//服务器socket()函数返回的套字接描诉符,用于通过网络发送和接收数据

    //int fd;//服务器accept()函数返回的一个信的套字结描诉符,用于与链接上的客户点进行数据的交换,原来的描诉符仍然被用于接受其他客户端的链接请求

    //int len;//用于recv()函数返回的字节长度

    sockaddr_in my_addr;//linux提供的专用于IP地址结构体

    sockaddr_in remote_addr;
    socklen_t sin_size;//不能用int,必须用socklen_t,等下去查查资料

    char buf[BUFSIZ];//存接收到的字节

        
    memset(&my_addr, 0, sizeof(my_addr));//让该结构体中的全部数据为0

    my_addr.sin_family = AF_INET;//地址族,定义为short类型,AF_INET表示他使用的是因特网地址族

    my_addr.sin_addr.s_addr = INADDR_ANY;//INADDR_ANY表示表示任意IP地址,也可以用inet_addr("192.168.1.1")来让IP地址转换成正确的IP地址结构

     my_addr.sin_port = htons(8000);//端口号,定义为short类型,后面的htons函数用于转换正确的端口号的值


    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket!");
        return 1;
    }

     if (bind(s,(sockaddr *)&my_addr,sizeof(sockaddr)) < 0)//创建的套字接必须被绑定到一个本地IP地址和端口号用于TCP通信

    {//第1个参数是套字接描诉符,第二个参数决定本地网络定义,第3个参数为sockaddr结构体的长度

        perror("bind!");
        return 1;//函数成果调用返回0,否则返回-1

    }

    listen(s,5);//开始监听客户端的连接,第一个参数是套字接描诉符,第2个参数表示表示监听队列的长度


    sin_size = sizeof(sockaddr_in);//结构体的长度


          pthread_t idid;//用于向全部客户端发送消息的线程。

     int retret = pthread_create(&idid,NULL,threadd,NULL);
       pthread_t id[100];//定义的接受客户端送数据的线程

      while(1)
      {
      if((fd[haha++] = accept(s,(sockaddr *)&remote_addr,&sin_size)) < 0)//当一个链接请求被接受以后,该函数返回一个新的套字接描述符号。这个描诉符用于与远程客户通信

      {//第一个参数为那个可以被监听的套字接描诉符,后面2个参数分别接受此结构的指针与长度的指针

         perror("accept!");
         return 1;
      }
    printf("accept client %s,(ID:%d)\n",inet_ntoa(remote_addr.sin_addr),fd[haha-1]);//显示接受的客户端的IP

    send(fd[haha-1],"Welcome to lthyxy's server!\n",28, 0);//发句欢迎词给每个接上来的客户端

    int ret = pthread_create(&id[haha-1],NULL,thread,NULL);//让线程进行,并进入对应的函数,为每个接入服务器的客户端创建一个接收线程,只要收到信息就显示出来。

    if (ret) { printf("create thread error!\n"); return 1;}//如过线程成功进行了就返回0,否则返回1?    

       }
    //pthread_join(id[haha],NULL);//等待其他线程都完成运行。

    //shutdown(fd[haha-1],2);

    //shutdown(s,2);//第一个参数套字接描诉符,后面的以后参数0表示不接受,1表示不发送,2表示既然不接受也不发送    

    return 0;
}


————————————————————————客户端————————————————————
#include <cstdio>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <cstring>

#include <string>

#include <iostream>

#include <pthread.h>

using namespace std;



int s;//用于套字接描诉符,为了给线程用


int allquit = 0;



void* thread(void *ss)

{

    int len = 1;

    char buf[BUFSIZ];

    while((len = recv(s,buf,BUFSIZ,0)) > 0)

    {

        buf[len-1] = '\0';

        string c(buf,buf+len);

        printf("%s\n",c.data());

        if(allquit) break;//跳出接收线程


    }

    return ss;

}



int main()

{

    int len;

    sockaddr_in remote_addr;

    char buf[BUFSIZ];

    

    memset(&remote_addr, 0, sizeof(remote_addr));

    remote_addr.sin_family = AF_INET;

    remote_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    remote_addr.sin_port = htons(8000);



    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)

    {

        perror("socket!");

        return 1;

    }



    if ((connect(s, (sockaddr *)&remote_addr, sizeof(sockaddr))) < 0)

    {

        perror("connect!");

        return 1;

    }



    printf("connected to lthyxy....\n");

    

    pthread_t id;

    int ret = pthread_create(&id, NULL, thread, NULL);

    if(ret)

    {

        printf("creat thread error!\n");

        return 1;

    }

    string kehuname("liutengfei:");

    while(1)

    {

        string k1(kehuname);

        string k2;

        string k3;

        while(getline(cin,k2))

        {

         k1 += k2;

         k3 = k2;

        }

        cin.clear();

        len = k1.size();

        strcpy(buf,k1.c_str());

        buf[len] = '\n';

        if (send(s,buf,len+1,0) < 0)

        {

            perror("write!");

            return 1;

        }

        if (k3[0] == 'q' && k3[1] == 'u' && k3[2] == 'i' && k3[3] == 't')

         {

         allquit = 1;

            break;

         }

    }

         pthread_join(id,NULL);

    shutdown(s,2);

    return 0;

}


上一篇:linux线程 基本函数 笔记
下一篇:简单的多线程编程