多路复用的聊天工具小代码
服务端:myhead.h
#ifndef _LIST_
#define _LIST_
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>
#include<strings.h>
typedef int data_t;
typedef struct node{
data_t data;
struct node *next;
}NODE;
NODE *creat_node(data_t data);
void insert(NODE *head, data_t data);
void _delete(NODE *head, data_t data);
void show_link(NODE *head);
#endif
list.c //主要拿来存登陆用户的文件描述符
#include "myhead.h"
NODE *creat_node(data_t data)
{
NODE *link_node = (NODE *)malloc(sizeof(NODE));
if( NULL == link_node )
exit(-1);
link_node->data = data;
link_node->next = NULL;
return link_node;
}
void insert(NODE *head, data_t data)
{
NODE *link_node = creat_node(data);
while(NULL != head->next)
{
head = head->next;
}
head->next = link_node;
}
void _delete(NODE *head, data_t data)
{
NODE *p =NULL;
while( head->next )
{
p = head;
head = head->next;
if( data == head->data )
{
p->next = head->next;
free(head);
return;
}
}
printf("%d outwith the link!\n", data);
}
void show_link(NODE *head)
{
while( head->next )
{
head = head->next;
printf("Connected ID:%d\t", head->data);
}
printf("\n");
}
server.c
#include "myhead.h"
int main()
{
int listenfd,connfd,maxfd,i,nbyte;
struct sockaddr_in myaddr, cliaddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
fd_set global_rdfs,current_rdfs;
char buf[10] = {0};
if (0 > listenfd)
{
perror("socket");
exit(-1);
}
int ii = 1;
int sres = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &ii, sizeof(ii));
if (0 > sres)
{
printf("setsockopt error\n");
exit(-1);
}
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(8888);
if(0 > bind(listenfd, (struct sockaddr *)&myaddr, sizeof(myaddr)))
{
perror("bind");
exit(-1);
}
listen(listenfd, 5);
printf("listening...\n");
FD_ZERO(&global_rdfs);
FD_SET(listenfd, &global_rdfs);
FD_SET(0, &global_rdfs);
maxfd = listenfd;
char send_buf[BUFSIZ] = {0};
char recv_buf[BUFSIZ] = {0};
int len = sizeof(cliaddr);
int size = 0;
NODE *head = creat_node(-1);
while(1)
{
current_rdfs = global_rdfs;
if(0 > select(maxfd + 1, ¤t_rdfs, NULL, NULL, 0))
{
perror("select");
exit(-1);
}
else
{
for (i = 0; i <= maxfd; ++i)
{
if(FD_ISSET(i, ¤t_rdfs))
{
if(i == listenfd)
{
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len);
if(0 > connfd)
{
perror("accept");
exit(-1);
}
printf("Connection from %s\tport %d\t ID:%d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port), connfd);
send(connfd, "welcome to server!", 30, 0);
FD_SET(connfd, &global_rdfs);
maxfd = maxfd > connfd ? maxfd : connfd;
insert(head, connfd);
}
else if(0 == i)
{
printf("useage:id:msg\n");
show_link(head);
fgets(send_buf, sizeof(send_buf), stdin);
if(!strncmp(send_buf, "quit", 4))
{
printf("goodbye!\n");
exit(-1);
}
char *p = strstr(send_buf, ":");
size = p - send_buf + 1;
snprintf(buf, size, "%s", send_buf);
send(atoi(buf), send_buf + size, strlen(send_buf) - size, 0);
}
else
{
if(0 >= (nbyte= recv(i, recv_buf, sizeof(recv_buf), 0)))
{
_delete(head,i);
close(i);
FD_CLR(i, &global_rdfs);
}
else
printf("recv%d:%s\n", i, recv_buf);
}
}
}
}
}
return 0;
}
用户端:
client.c
#include <myhead.h>
#define MAXSIZE 1024
int main(int argc, char *argv[]) //带命令行ip
{
if(2 != argc)
{
printf("useage:%s + server's ip\n");
exit(-1);
}
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(0 > sockfd)
{
perror("socket");
exit(-1);
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(argv[1]);
servaddr.sin_port = htons(8888);
char buf[MAXSIZE] = {0};
connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
recv(sockfd, buf, sizeof(buf), 0);
puts(buf);
int i;
fd_set readfd;
int maxfd = -1;
char recv_buf[MAXSIZE] = {0};
char send_buf[MAXSIZE] = {0};
while(1)
{
FD_ZERO(&readfd);
FD_SET(0, &readfd);
maxfd = maxfd > 0 ? maxfd : 0;
FD_SET(sockfd, &readfd);
maxfd = maxfd > sockfd ? maxfd : sockfd;
if(0 > select(maxfd + 1, &readfd, NULL, NULL, NULL))
{
perror("select");
exit(-1);
}
for(i=0; i<=maxfd; i++)
{
if(FD_ISSET(i, &readfd))
{
if(i == sockfd)
{
if(0 >= recv(sockfd, recv_buf, sizeof(recv_buf), 0))
exit(-1);
printf("recv:%s", recv_buf);
memset(recv_buf, 0, sizeof(recv_buf));
}
if(0 == i)
{
fgets(send_buf, sizeof(send_buf), stdin);
send(sockfd, send_buf, strlen(send_buf) + 1, 0);
memset(send_buf, 0, sizeof(send_buf));
}
}
}
}
return 0;
}
小弟socket编程差劲,目前写的只能1对多聊天,再准备写个好点的多对多聊天代码,各位大侠给点建议,不要多进程的,那个很浪费资源
[ 本帖最后由 遗矢的老人 于 2012-8-23 00:56 编辑 ]