SOCKET网络编程:Linux下实现聊天室
程序介绍:本聊天室程序在Ubuntu下,采用C语言实现,结构为Client/Server结构;
服务端程序通过共享存储区存储聊天数据,并发送给每个连接的客户端;
服务端程序和客户端程序都是通过父子进程分别负责发送和接收数据的,以避免数据冲撞;
需按以下格式调用客户端程序: 服务端主机IP 端口号(本程序设定为:3490) 用户名(在聊天室中显示的用户名)
程序截图:
//--------------------------------服务端----------------------------------------------
//--------------------------------客户端1:真水无香--------------------------------------
socket编程实验的心得体会
//--------------------------------客户端2:蜡笔小新--------------------------------------
程序代码如下:
//--------------------------------server.c--------------------------------------------------
//包含工程所需的头文件
#include<stdio.h> 
#include<stdlib.h>
#include<sys/types.h>  //数据类型定义
#include<sys/stat.h>
#include<netinet/in.h>  //定义数据结构sockaddr_in
#include<sys/socket.h>  //提供socket函数及数据结构
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/ipc.h>
#include<errno.h>
#include<sys/shm.h>
#include<time.h>
#define PERM S_IRUSR|S_IWUSR 
#define MYPORT 3490  //宏定义定义通信端口
#define BACKLOG 10 //宏定义,定义服务程序可以连接的最大客户数量
#define WELCOME "|----------Welcome to the chat room! ----------|"  //宏定义,当客户端连接服务端时,想客户发送此欢迎字符串
//转换函数,将int类型转换成char *类型
void itoa(int i,char*string)
{
  int power,j;
  j=i;
  for(power=1;j>=10;j/=10)
    power*=10;
  for(;power>0;power/=10)
  {
    *string++='0'+i/power;
    i%=power;
  }
  *string='\0';
}
//得到当前系统时间
void get_cur_time(char * time_str)
{
  time_t timep;
  struct tm *p_curtime;
  char *time_tmp;
  time_tmp=(char *)malloc(2);
  memset(time_tmp,0,2);
  memset(time_str,0,20);
  time(&timep);
  p_curtime = localtime(&timep);
  strcat(time_str," (");
  itoa(p_curtime->tm_hour,time_tmp);
  strcat(time_str,time_tmp);
  strcat(time_str,":");
  itoa(p_curtime->tm_min,time_tmp);
  strcat(time_str,time_tmp);
  strcat(time_str,":");
  itoa(p_curtime->tm_sec,time_tmp);
  strcat(time_str,time_tmp);
  strcat(time_str,")");
  free(time_tmp);
}
//创建共享存储区
key_t shm_create()
{
  key_t shmid;
  //shmid = shmget(IPC_PRIVATE,1024,PERM);
  if((shmid = shmget(IPC_PRIVATE,1024,PERM)) == -1)
  {
    fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno));
    exit(1);
  }
  return shmid;
}
//端口绑定函数,创建套接字,并绑定到指定端口
int bindPort(unsigned short int port)
  int sockfd;
  struct sockaddr_in my_addr;
  sockfd = socket(AF_INET,SOCK_STREAM,0);//创建基于流套接字
  my_addr.sin_family = AF_INET;//IPv4协议族
  my_addr.sin_port = htons(port);//端口转换
  my_addr.sin_addr.s_addr = INADDR_ANY;
  bzero(&(my_addr.sin_zero),0);
  if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr)) == -1)
  {
    perror("bind");
    exit(1);
  }
  printf("bing success!\n");
  return sockfd;
}
int main(int argc, char *argv[])
{
  int sockfd,clientfd,sin_size,recvbytes; //定义监听套接字、客户套接字
  pid_t pid,ppid//定义父子线程标记变量
  char *buf, *r_addr, *w_addr, *temp, *time_str;//="\0"; //定义临时存储区
  struct sockaddr_in their_addr//定义地址结构
  key_t shmid;
  shmid = shm_create(); //创建共享存储区
  temp = (char *)malloc(255);
  time_str=(char *)malloc(20);
  sockfd = bindPort(MYPORT);//绑定端口
  while(1)
  {   
    if(listen(sockfd,BACKLOG) == -1)//在指定端口上监听
    {
      perror("listen");
      exit(1);
    }
    printf("\n");
    if((clientfd = accept(sockfd,(struct sockaddr*)&their_addr,&sin_size)) == -1)//接收客户端连接
    {
      perror("accept");
      exit(1);
    }
    printf("accept from:%d\n",inet_ntoa(their_addr.sin_addr));
    send(clientfd,WELCOME,strlen(WELCOME),0);//发送问候信息
    buf = (char *)malloc(255);
   
    ppid = fork();//创建子进程
    if(ppid == 0)
    {
      //printf("ppid=0\n");
      pid = fork();  //创建子进程 
      while(1)
      {
        if(pid > 0)
        {
            //父进程用于接收信息
          memset(buf,0,255);
          //printf("recv\n");
          //sleep(1);
          if((recvbytes = recv(clientfd,buf,255,0)) <= 0)
          {
            perror("recv1");
            close(clientfd);
            raise(SIGKILL);
            exit(1);
          }
          //write buf's data to share memory
          w_addr = shmat(shmid, 0, 0);
                memset(w_addr, '\0', 1024);
          strncpy(w_addr, buf, 1024);
          get_cur_time(time_str);
          strcat(buf,time_str);
          printf(" %s\n",buf);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。