linux局域网通讯源码(服务器多路复用和客户端多进程模式)(socket)客户端

原创 2012年03月30日 23:28:34

/*client.c*/

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include<malloc.h>
//#include<curses.h>//linux图形化编程界面函数

#define PORT 4321
#define BUFFER_SIZE 1024

typedef struct user
{
   struct sockaddr_in users_sockaddr;//用户IP
   int user_fd;//用户连接套接字
   char *user_name;//用户别名
   char buf[BUFFER_SIZE];//用户发的信息
   char del[4];//删除下线用户信号标志位
   int rece_id;
   struct user *Next;
}USER_List,*pUSER_List;

pUSER_List craet_USER_listhead()
{
  pUSER_List pHead=(pUSER_List)malloc(sizeof(USER_List));
  if(pHead==NULL)
  {
   printf("The Dynamic memory allocation is fail\n");
   exit(-1);
  }
   pHead->Next=NULL;
   return pHead; 
}

pUSER_List craet_USER_buff()
{
 pUSER_List pbuff=(pUSER_List)malloc(sizeof(USER_List));
   if(pbuff==NULL)
   {
    printf("The Dynamic memory allocation is fail\n");
    exit(-1);
   }
   return pbuff; 
}


pUSER_List insert_USERList(pUSER_List p,struct sockaddr_in uaddr,int fd,char *name)
{
 int i=0;
 pUSER_List pNew=(pUSER_List)malloc(sizeof(USER_List));
 if(pNew==NULL)
   {
  printf("The Dynamic memory allocation is fail\n");
  exit(-1);
   }
 
   pNew->users_sockaddr=uaddr;
   pNew->user_fd=fd;

 while(p->Next)
 {
  p=p->Next;
 }
 
 p->Next=pNew;
 pNew->Next=NULL;
 
return;
}

void delet_List(pUSER_List p,int fd)
{
 pUSER_List q;
    do
 {
  q=p;//先保存前一个地址
  p=p->Next;
  if(p->user_fd==fd)
  {
        q->Next=p->Next;
  free(p);
  }
  
 }while(p->Next);
}


char * choosechatmode(int sockfd,char *c)
{   int sendbytes,fd;
 printf("Please choose the many people chat?or single people chat\n\n");
 printf("many people chat please input manp\n");
 printf("single people chat please input sinp\n");
  scanf("%s",c);
 while((strcmp("sinp",c)!=0)&&(strcmp("manp",c)!=0))
 {
    printf("Please input the correct command!!\n");
 scanf("%s",c);
 }
return c; 
}

void show_online_users_list(pUSER_List USER)
{
 printf("The online user list:--------------------------------\n");
   do
    {
   USER=USER->Next;
   printf("USER Socket is %d:",USER->user_fd);
   printf("  The USER IP:%s\n",(char*)inet_ntoa(USER->users_sockaddr.sin_addr));
    }while(USER->Next->Next);
  printf("******************************************************\n");
}

int chack_socket_number(pUSER_List USER,int fd)
{
  while(USER->Next)
  {
    if(USER->user_fd==fd)return 0;//说明上线用户列表中有这个用户
    USER=USER->Next;
  }
  printf("The socket number In the online_user list is not exit!!!\n");
  return 1;
}

int main(int argc, char *argv[])
{
 
    pUSER_List USER,zero;
 USER_List buff;
 USER_List rebuff;
 int recvbytes;
 int sockfd, sendbytes;
 struct hostent *host;
 struct sockaddr_in serv_addr;
 char c[10];
 USER=craet_USER_listhead();//创建用户列表文件?    zero=USER;
    zero=USER;
    pid_t child;
  int fd;
 /*地址解析函数*/
 if ((host = gethostbyname(argv[1])) == NULL)
 {
  perror("gethostbyname");
  exit(1);
 }

 /*创建socket*/
 if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
 {
  perror("socket");
  exit(1);
 }
 
 /*设置sockaddr_in 结构体中相关参数*/
 serv_addr.sin_family = AF_INET;
 serv_addr.sin_port = htons(PORT);
 serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
 bzero(&(serv_addr.sin_zero), 8);
 
 /*调用connect函数主动发起对服务器端的连接*/
 if(connect(sockfd,(struct sockaddr *)&serv_addr, sizeof(struct sockaddr))== -1)
 {
  perror("connect");
  exit(1);
 }
 
    //接收用户在线用户列表
   while(1)
   {
    memset(&buff,0,sizeof(USER_List));
    if ((recvbytes = recv(sockfd, &buff, sizeof(USER_List), 0)) < 0)
  {
   perror("recv"); 
  }
 
 insert_USERList(USER,buff.users_sockaddr,buff.user_fd,"r");
 if(buff.user_fd==6000)break;//如果接收到这个标志位,就说明接收完毕
   }
  
   show_online_users_list(USER);//显示在线用户列表
 
    choosechatmode(sockfd,c);//群聊还是私聊模式选择
   
 /*发送消息给服务器端*/
  memset(&buff,0,sizeof(USER_List)); 
  if(strcmp(c,"sinp")==0)//如果选择单人聊天模式
 { 
  do
  {
      printf("Please input the user liner number!!\n");
   scanf("%d",&fd);
   buff.rece_id=fd;//就把选择目标ID存入。
  }while(chack_socket_number(USER,fd));//检查目标ID是否在上线用户列表中
 }
  strcpy(buff.buf,c);//把聊天模式选择标志位加入数组头
   

  printf("You can chat now!\n");

 
  /* 创建子进程 */
 if((child=fork())==-1)
 {
  printf("Fork Error \n");
  exit(1);
 }
    while(1)
   {
  if(child==0) // 子进程
  {
     scanf("%s",buff.buf+4);
     if(strncmp("sinp",buff.buf+4,4)==0)//如果切换到私聊模式
     {
         show_online_users_list(USER);//显示在线用户列表
               do
       {
                  printf("Please input the user liner number!!\n");
             scanf("%d",&fd);
             buff.rece_id=fd;//就把选择目标ID存入。
          }while(chack_socket_number(USER,fd));//检查目标ID是否在上线用户列表中
          strcpy(buff.buf,"sinp");//把聊天模式选择标志位加入数组头
     }
     else if(strncmp("manp",buff.buf+4,4)==0)
     {
          strcpy(buff.buf,"manp");//把聊天模式选择标志位加入数组头
     }
    
     if ((sendbytes = send(sockfd, &buff,sizeof(USER_List), 0)) == -1)
     {
      perror("send");
      exit(1);
     }
  }
  
  
  else if(child>0)//父进程
  {
   memset(&rebuff, 0, sizeof(USER_List));
   if (recv(sockfd, &rebuff,sizeof(USER_List), 0) > 0)
   {
    if(strcmp(rebuff.del,"del")==0)//判断是否有人离线
    {
                   printf("\33[33m\33[1m");
       printf("The %d is outline!!\n",rebuff.user_fd);
       printf("\33[0m\n");
       delet_List(USER,rebuff.user_fd);//将下线用户从用户列表中删除
    }

    if(strcmp(rebuff.del,"inl")==0)//判断是否有人上线
    {
                   printf("\33[33m\33[1m");
       printf("The %d is inline!!\n",rebuff.user_fd);
       printf("\33[0m\n");
       insert_USERList(USER,rebuff.users_sockaddr,rebuff.user_fd,"w");//将新上线用户追加到列表
    }
    else
    {
    printf("\33[33m\33[1m");
    printf("Received %d:%s\n",rebuff.rece_id,rebuff.buf+4);
    printf("\33[0m\n");
    }
   }
  }

   } 
 
close(sockfd);
exit(0);
}

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

多进程实现linux 下即时聊天软件

网络编程项目要求 一、 实现目标 一个在Linux下可以使用的聊天软件,要求至少实现如下功能: 1. 采用Client/Server架构 2. Client A 登陆聊天服务器前,需要...

多进程、共享内存的网络聊天室

好久没写网络聊天室了,去年暑假可以说写了一暑假,最近复习这些,又因为我一直偏向于多线程,就用多进程复习一下。下面给出昨天写的基于多进程、共享内存的网络聊天室代码。每个进程负责一个连接,多个进程之间仅共...

java多路复用socket客户端.

  • 2017年12月07日 14:38
  • 2KB
  • 下载

socket编程:多路复用I/O服务端客户端之select

其实在之前的TCP之中,我们编程实现了多进程,多线程机制下的TCP服务器,但是对于这种的TCP服务器而言,存在太大的资源局限性。所以我们可以是用I/0模型中的多路复用I/O模型来进行编程。他的具体思想...

socket编程:多路复用I/O服务端客户端之poll

一. 关于poll    对于IO复用模型,其优点无疑是免去了对一个个IO事件就绪的等待,转而代之的是同时对多个IO数据的检测,当检测等待的事件中至少有一个就绪的时候,就会返回告诉用户进程“已经有数据...

基于TCP客户端和服务器的I/O多路复用

一、基于TCP/IP协议的基本循环服务器 tcp_server.c [cpp] view plain copy   #include    #...
  • zscfa
  • zscfa
  • 2016年12月05日 00:09
  • 439

Python处理多个客户端连接---多路复用选择服务器

多路复用 到目前为止,我们已经看到如何用分支进程和派生线程来同时处理多个客户端,以及一个封装了这两个方案的库类。在这两种方法下,所有的客户端处理程序似乎都是彼此并行运行(即在同一时间内)运行的,所以...

linux socket 服务器与客户端多进程通信

linux socket 多进程 server 与 client 通信

tcp 多路复用实现 两个客户端之间的通信

/******************************* 服务器端  ****************************/ #include #include #inclu...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux局域网通讯源码(服务器多路复用和客户端多进程模式)(socket)客户端
举报原因:
原因补充:

(最多只允许输入30个字)