您的位置:首页 > 理论基础 > 计算机网络

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

2012-05-08 20:39 645 查看
//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()的错误提示
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息