基于Linux C 的简单聊天程序
服务器端:
// tcp-server.c
//tcp server
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#define SERVER_PORT 8080
#define NET_IP "127.0.0.1"
#define MAX_LINK 10
#define BUF_SIZE 1024
#define STATU_CONNECT 1
#define STATU_DISCONN 0
int main(int argc, char** argv)
{
char buf[BUF_SIZE],tmp_buf[BUF_SIZE];
unsigned char conn_fd[FD_SETSIZE];
struct sockaddr_in server_sin,client_sin; //ip
int server_sock_fd,client_sock_fd; //socket 文件描述符
int fd,tmp_fd;//temp fd
int ctrl_flag=1; //端口复用标志
int recvLen;
socklen_t client_len; //client_sin 长度,发送数据时用到
fd_set inset,tmp_inset;
server_sock_fd=socket(AF_INET,SOCK_STREAM,0);
if(server_sock_fd<0)
{
perror("socket");
exit(1);
}
printf("socket fd is %d\n",server_sock_fd);
bzero(&server_sin,sizeof(server_sin));
server_sin.sin_family=AF_INET;
server_sin.sin_port=htons(SERVER_PORT);
server_sin.sin_addr.s_addr=htonl(INADDR_ANY);//用这句绑定的是默认ip
if(argc==2)
{
if(inet_aton(argv[1],&server_sin.sin_addr)<0)//这里绑定的是指定地址
{
perror("inet_aton");
close(server_sock_fd);
exit(1);
}
}
setsockopt(server_sock_fd,SOL_SOCKET,SO_REUSEADDR,&ctrl_flag,sizeof(ctrl_flag));//设置端口重用
if(bind(server_sock_fd,(struct sockaddr *)&server_sin,sizeof(server_sin))<0)
{
perror("bind");
close(server_sock_fd);
exit(1);
}
if(listen(server_sock_fd,MAX_LINK)<0)
{
perror("listen");
close(server_sock_fd);
exit(1);
}
printf("listening...\n");
FD_ZERO(&inset);
FD_SET(server_sock_fd,&inset);
FD_SET(0,&inset);
conn_fd[server_sock_fd]=STATU_CONNECT;
while(1)
{
FD_ZERO(&tmp_inset);
tmp_inset=inset;
client_len=sizeof(client_sin);
memset(buf,0,sizeof(buf));
memset(tmp_buf,0,sizeof(tmp_buf));
if(!select(FD_SETSIZE,&tmp_inset,NULL,NULL,NULL)>0)//监控输入文件表述符
{
perror("select");
}
for(fd=0;fd<FD_SETSIZE;fd++)
{
if(FD_ISSET(fd,&tmp_inset)>0)
{
if(fd==0)
{
if(read(0,buf,sizeof(buf))>0)
{
buf[strlen(buf)]='\0';
if(strcmp(buf,"exit\n")==0)
{
exit(0);
}
sprintf(tmp_buf,"system message: %s",buf);
for(tmp_fd=0;tmp_fd<FD_SETSIZE;tmp_fd++)
{
if(conn_fd[tmp_fd] && tmp_fd!=server_sock_fd && tmp_fd!=fd)
{
send(tmp_fd,tmp_buf,strlen(tmp_buf),0);
}
}
}
}
else if(fd==server_sock_fd)
{
if((client_sock_fd=accept(server_sock_fd,(struct sockaddr *)&client_sin,&client_len))==-1)
{
perror("accept");
close(server_sock_fd);
exit(1);
}
FD_SET(client_sock_fd,&inset);
conn_fd[client_sock_fd]=STATU_CONNECT;
sprintf(buf,"new connection : fd=%d\t ip=%s\n",client_sock_fd,inet_ntoa(client_sin.sin_addr));
printf("%s",buf);
for(tmp_fd=0;tmp_fd<FD_SETSIZE;tmp_fd++)
{
if(conn_fd[tmp_fd] && tmp_fd!=server_sock_fd && tmp_fd!=fd)
{
send(tmp_fd,buf,strlen(buf),0);
}
}
client_sock_fd=-1;
}
else
{
recvLen=recv(fd,buf,sizeof(buf),0);
if(recvLen<=0)
{
sprintf(buf,"client %d(socket) has disconnect.\n",fd);
printf("client %d(socket) has disconnect.\n",fd);
FD_CLR(fd,&inset);
conn_fd[fd]=STATU_DISCONN;
close(fd);
for(tmp_fd=0;tmp_fd<FD_SETSIZE;tmp_fd++)
{
if(conn_fd[tmp_fd] && tmp_fd!=server_sock_fd && tmp_fd!=fd)
{
send(tmp_fd,buf,strlen(buf),0);
}
}
}
else
{
buf[strlen(buf)]='\0';
sprintf(tmp_buf,"fd %d say: %s",fd,buf);
printf("recieve from client %d: %s",fd,buf);
for(tmp_fd=0;tmp_fd<FD_SETSIZE;tmp_fd++)
{
if(conn_fd[tmp_fd] && tmp_fd!=server_sock_fd && tmp_fd!=fd)
{
send(tmp_fd,tmp_buf,strlen(tmp_buf),0);
}
}
}//if(recvLen<=0)
}//if(fd==server_sock_fd)
}//if(FD_ISSET(fd,&tmp_inset)>0)
}//for(fd=0;fd<FD_SETSIZE;fd++)
}//while(1)
for(tmp_fd=0;tmp_fd<FD_SETSIZE;tmp_fd++)
{
if(conn_fd[tmp_fd] && tmp_fd!=server_sock_fd)
{
close(tmp_fd);
}
}
close(server_sock_fd);
return 0;
}
编译:gcc -o talk_tcp_server talk_tcp_server.c