TCP/IP Scoket编程之UDP聊天室(C语言实现)

//room.c 文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "wwb.h"


#define BUFSIZE 255


int main(int argc, char *argv[]) {
//
    if (argc != 2) {
        printf("Parameter(s): <Input Your Name> \n");
        exit(1);
    }
char *clnName = argv[1];


//
    in_port_t servPort  = 5000;
    char *bcIP = "172.18.81.255";
    in_port_t bcPort = 5000;


    pid_t pid;
    pid = fork();
    if(pid > 0) {  //Parent Process for send msg
        int sock1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (sock1 < 0) {
            printf("socket() failed\n");
            exit(1);
        }
        int on = 1;
//设置socket状态
        setsockopt(sock1, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));


        struct sockaddr_in bcAddr;   //指定地址
        memset(&bcAddr, 0, sizeof(bcAddr));
        bcAddr.sin_family = AF_INET;
        int rtnVal = inet_pton(AF_INET, bcIP, &bcAddr.sin_addr.s_addr);//二进制   字符串地址转换
        if (rtnVal == 0) {
            printf("inet_pton() failed, invalid address string\n");
            exit(1);
        }
        else if (rtnVal < 0) {
            printf("inet_pton() failed\n");
            exit(1);
        }
        bcAddr.sin_port = htons(bcPort);
        
        //send "hello"
        char *str="hello";
//经socket传送数据
        ssize_t numBytes1 = sendto(sock1, str, strlen(str), 0, (struct sockaddr*)&bcAddr, sizeof(bcAddr));
//传用户名
ssize_t clnName1 = sendto(sock1, clnName, strlen(clnName), 0, (struct sockaddr*)&bcAddr, sizeof(bcAddr));
        if (numBytes1 < 0) {
            printf("sendto() failed\n");
            exit(1);
        }


        while(1) {
            int iExit = 0;
            char strMsg[256] = {0};
            printf("you say:");
            fgets(strMsg, 256, stdin);              
            if(!strcmp(strMsg, "quit\n")) { //比较字符串
                memset(strMsg, strlen(strMsg),0);//将一段内存空间填入某值
                strcpy(strMsg, "bye\n");//拷贝字符串to strMsg
                iExit = 1;
            }
            numBytes1 = sendto(sock1, strMsg, strlen(strMsg)-1, 0, (struct sockaddr*)&bcAddr, sizeof(bcAddr));
   clnName1 = sendto(sock1, clnName, strlen(clnName), 0, (struct sockaddr*)&bcAddr, sizeof(bcAddr));
            if (numBytes1 < 0) {
                printf("sendto() failed\n");
                exit(1);
            }


            if(iExit) {
                exit(0);
            }
        }
    }
    else if(pid == 0) { //child process  for receive msg
        int sock2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (sock2 < 0) {
            printf("socket() failed\n");
            exit(1);
        }
          
        //二进制  字符串地址转换
        struct sockaddr_in servAddr;
        memset(&servAddr, 0, sizeof(servAddr));
        servAddr.sin_family = AF_INET;
        servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servAddr.sin_port = htons(servPort);
        //对socket定位
        if (bind(sock2, (struct sockaddr*) &servAddr, sizeof(servAddr)) < 0) {
            printf("bind() failed\n");
            exit(1);
        }
       
        while(1) {
            struct sockaddr_in fromAddr;
            socklen_t fromAddrLen = sizeof(fromAddr);


           // char buffer[BUFSIZE] = {0};
char buffer_1[BUFSIZE] = {0};


   //经socket接收数据
            ssize_t numBytes2 = recvfrom(sock2, buffer_1, BUFSIZE, 0, (struct sockaddr *) &fromAddr, &fromAddrLen);
 char buffer_2[BUFSIZE] = {0};
   ssize_t clnName2 = recvfrom(sock2, buffer_2, BUFSIZE, 0, (struct sockaddr *) &fromAddr, &fromAddrLen);
            if (numBytes2 < 0) {
                printf("recvfrom() failed\n");
                exit(1);
            } 
            
            char fromName[50] = {0};
            char ctime[50] = {0}; 
            inet_ntop(AF_INET, &fromAddr.sin_addr.s_addr, fromName, sizeof(fromName));
   
            if(!strcmp(buffer_1,"hello")) {  //if buffer=hello  return 0
                WriteLog("%s (%s) enter room\n", GetSysTime(ctime),  buffer_2);
            } 
            else  if(!strcmp(buffer_1,"bye")) { 
                WriteLog("%s (%s) leave room\n", GetSysTime(ctime), buffer_2);
            } 
            else {
                char ctime[50] = {0};
                WriteLog("[%s] o(*_*)o %s say:%s\n", GetSysTime(ctime), buffer_2,buffer_1);
            }
        }
    }
}

//getSysTime.c 文件
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>


int WriteLog(const char *format, ...)
{
    FILE *fp;
    fp=fopen("recv.txt", "a+");
    if(fp==NULL) return -1;


    va_list arg_ptr;
    va_start(arg_ptr, format);
    vfprintf(fp, format, arg_ptr);
    va_end(arg_ptr);
    
    fclose(fp);
    return 0;
}


char* GetSysTime(char *out)
{
  time_t timep;
  struct tm *p;
  time(&timep);
  p=localtime(&timep);
  int year=(1900+p->tm_year);
  int month=(1+p->tm_mon);
  int day=p->tm_mday;
  int hour=p->tm_hour;
  int minute=p->tm_min;
  int second=p->tm_sec;
  sprintf(out,"%d-",year);
  if(month<10)  sprintf(out+5,"0%d-",month);   else sprintf(out+5,"%d-",month);
  if(day<10)    sprintf(out+8,"0%d ",day);     else sprintf(out+8,"%d ",day);
  if(hour<10)   sprintf(out+11,"0%d:",hour);   else sprintf(out+11,"%d:",hour);
  if(minute<10) sprintf(out+14,"0%d:",minute); else sprintf(out+14,"%d:",minute);
  if(second<10) sprintf(out+17,"0%d",second);  else sprintf(out+17,"%d",second);
  return out;
}


/*
int main()
{
  char time[50];
  int i=10;
  char *s="hello";
  WriteLog("%s,%d,%s\n", GetSysTime(time),i,s);
}
*/

//getSysTime.h 文件
int WriteLog(const char *format, ...);             //写日志文件
char* GetSysTime(char* time);                      //得到系统时间


//linux中,gcc -o room room.c getSysTime.c
./room [your name]

//2012.5.10修改:在138行再添加一条语句---exit(0);这样做的目的是,用户输入quit退出之后,子进程也同样退出,否则,再次登录的时候,会出现bind failed()的错误提示
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值