好吧,代码比较粗糙,有机会了再改:
分析:
1)客户端登录输入昵称
2)上线提醒给所有人
3)下线提醒给所有人
4)服务器接收客户端消息然后分发给所有在线端
服务端代码:
ps:编译的时候别忘了 -pthread
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>
#define MAX_CNT 100
void* dealMsg(void* client);
int find();
struct CLIENT {
int fd;
short port;
char ip[16];
char name[20];
};
struct CLIENT client[MAX_CNT]= {0,0,0,0};
int count = 0;//数组中数量
int sockfd = -1;
int main() {
void closefd();
signal(SIGINT, closefd);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd) perror("socket"),exit(-1);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(2222);
addr.sin_addr.s_addr = inet_addr("172.16.11.34");
int reuseaddr = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr
, sizeof(reuseaddr));
int res = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
if (-1 == res) perror("bind"),exit(-1);
listen(sockfd, MAX_CNT);
while (1) {
struct sockaddr_in from;
socklen_t len = sizeof(from);
int fd = accept(sockfd, (struct sockaddr*)&from, &len);
if (-1 == fd) perror("accept"),exit(-1);
printf("server started...\n");
if(count >= MAX_CNT) continue;
int idx = find();
strcpy(client[idx].ip, inet_ntoa(from.sin_addr));
client[idx].port = ntohs(from.sin_port);
client[idx].fd = fd;
recv(fd, client[idx].name, 20, 0);//接收昵称
char msg[100] = {};
sprintf(msg,"%s上线了\n", client[idx].name);
printf("%s is connected!\n", client[idx].name);
int i = 0;
for (i = 0; i < MAX_CNT && strcmp(client[i].name, ""); ++i) {
send(client[i].fd, msg, strlen(msg), 0);
}
pthread_t id;
pthread_create(&id, 0, dealMsg, &client[idx]);
++count;
}
return 0;
}
void* dealMsg(void* p) {
struct CLIENT* info= p;
while (1) {
char recvmsg[100] = {};
recv(info->fd, recvmsg, sizeof(recvmsg), 0);
char msg[200] = {};
if (0 == strcmp(recvmsg, "quit")) {
sprintf(msg, "%s下线\n", info->name);
int i = 0;
for (i = 0; i < MAX_CNT && strcmp(client[i].name, ""); ++i) {
send(client[i].fd, msg, strlen(msg), 0);
}
break;
}
sprintf(msg,"%s:%s说:\n%s\n", info->ip, info->name, recvmsg);
int i = 0;
for (i = 0; i < MAX_CNT && strcmp(client[i].name, ""); ++i) {
send(client[i].fd, msg, strlen(msg), 0);
}
}
strcpy(info->ip, "");
strcpy(info->name, "");
info->port = 0;
close(info->fd);
info->fd = 0;
--count;
}
int find() {//找到元素为空的最小下标
int i = 0;
for (i = 0; i < MAX_CNT; ++i) {
if(client[i].port ==0) break;
}
return i;
}
void closefd() {
close(sockfd);
printf("server shutdown...\n");
exit(0);
}
客户端代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
void* recvMsg(void *p);
char ip[16] = "172.16.11.34";
int port = 2222;
char name[20];
int main() {
char ip1[15] = {};
int port1 = 0;
printf("please iput server ip:\n");
scanf("%s", ip1);
if (0 != strcmp(ip1, "0")) strcpy(ip, ip1);
printf("please iput server port:\n");
scanf("%d", &port1);
if (0 != port1) port = port1;
printf("please iput your name:\n");
scanf("%s", name);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
int res = connect(sockfd, (struct sockaddr*)&addr,sizeof(addr));
if (-1 == res) perror("connect"),exit(-1);
//开线程去收信息
pthread_t id = 0;
res = pthread_create(&id, 0, recvMsg, &sockfd);
//发送昵称
send(sockfd, name, strlen(name), 0);
while (1) {//发送信息
char sendmsg[100] = {};
printf("\n");
scanf("%s", sendmsg);
scanf("%*[^\n]");
scanf("%*c");
send(sockfd, sendmsg, strlen(sendmsg), 0);
if(0 == strcmp(sendmsg, "quit")) break;
}
close(sockfd);
return 0;
}
void* recvMsg(void *p) {
int* fd = p;
while (1) {
char recvmsg[100] = {};
recv(*fd, recvmsg, sizeof(recvmsg), 0);
printf("%s",recvmsg);
}
}