//客户端
#include "header.h"
// 客户端接收消息的线程函数
void* recv_func(void *args)
{
char buf[BUFFER_SIZE];
int sock_fd = *(int*)args;
while(true) {
memset(buf,0,BUFFER_SIZE);
int n = read(sock_fd, buf, BUFFER_SIZE);
buf[n+1]="\0";
if(n <= 0) break;
else
printf("%s",buf);
}
close(sock_fd);
exit(0);
}
// 客户端和服务端进行通信的处理函数
void process(int sock_fd)
{
pthread_t td;
pthread_create(&td, NULL, recv_func, (void*)&sock_fd);// 新开个线程来接收消息,避免了一读一写的原始模式
char buf1[BUFFER_SIZE];
while(true)
{
memset(buf1,0,BUFFER_SIZE);
int n = read(STDIN_FILENO, buf1, BUFFER_SIZE);
buf1[n+1] = '\0'; //貌似标准读入不会有字符串结束符的,需要自己手动添加
if( (write(sock_fd, buf1, n+1)) < 0 )
{
printf("send error!\n");
}
}
close(sock_fd);
}
int main(int argc, char *argv[])
{
struct hostent *host;
struct sockaddr_in server;
bzero(&server, sizeof(server));
/*
assert(argc == 2);//判断条件是否为真,否则退出
if ((host = gethostbyname(argv[1])) == NULL){
perror("gethostbyname error!\n");
exit(1);
}
*/
server.sin_family = AF_INET;
// server.sin_addr = *((struct in_addr *)host->h_addr); // 用第一个参数作为连接服务器端的地址
server.sin_addr.s_addr = inet_addr(SERVER_IP);
server.sin_port = htons(PORT);
int sc = socket(AF_INET, SOCK_STREAM, 0);
if(sc < 0) {
perror("socket error");
exit(-1);
}
int err = connect(sc, (struct sockaddr*)&server, sizeof(server));
if(err < 0) {
perror("connect error");
exit(-2);
}
process(sc);
close(sc);
return 0;
}
头文件:
#ifndef _HEADER_H
#define _HEADER_H
#include <stdio.h> //printf perror
#include <sys/socket.h> //socket blind listen accept connect
#include <unistd.h> //read and write
#include <sys/types.h> //size_t,time_t,pid_t等类型
#include <stdlib.h> //NULL exit
#include <string.h> //sizeof
#include <netinet/in.h>
#include <netdb.h>
#include <assert.h> //assert
#define PORT 23456
#define SERVER_IP "120.77.214.213"
#define BUFFER_SIZE 1024
#define true 1
#endif
Makefile:
OBJS = client.o
CC = gcc
CFLAGS = -w
server : $(OBJS)
$(CC) $(OBJS) -o client -pthread
server.o : client.c header.h
$(CC) $(CFLAGS) -c client.c -o client.o
make clean:
rm -rf *.o client
服务端:
#include <stdio.h> //printf perror
#include <sys/socket.h> //socket blind listen accept connect
#include <unistd.h> //read and write
#include <sys/types.h> //time_t
#include <stdlib.h> //NULL
#include <string.h> //sizeof
#include <netinet/in.h>
#include <netdb.h> //hostnent
#include <pthread.h> //phread
#include <time.h> //time
#define PORT 23456
#define MAX_QUE_CONN 5 //靠靠靠
#define MAX_MEM 10 //靠靠靠
#define BUFFER_SIZE 1024
#define NAME_SIZE 20
#define true 1
void *quit(void *arg);
void *rcv_mes(void *arg);
int sockfd,client_fd[MAX_MEM];
int main(){
struct sockaddr_in server_sockaddr,client_sockaddr;
int r_bytes;
socklen_t len = sizeof(struct sockaddr);
time_t ticks;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("Socket error!\n");
exit(1);
}
/*设置sockaddr_in 结构体中相关参数*/
server_sockaddr.sin_family = AF_INET; //Ipv4
server_sockaddr.sin_port = htons(PORT); //htons:主机字节序(小)-> 网络字节序(大)
server_sockaddr.sin_addr.s_addr = INADDR_ANY; //all ip can connect
memset(server_sockaddr.sin_zero,0,8); //填充0以保持与struct sockaddr同样大小
/*bind sockfd*/
if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr)) == -1){
perror("Bind error!\n");
exit(1);
}
/*listen*/
if ( listen( sockfd, MAX_QUE_CONN) == -1){
perror("Listen error!\n");
exit(1);
}
printf("Listening........\n");
/*创建一个线程,对服务器程序进行管理(关闭)*/
pthread_t thread;
if ((pthread_create(&thread, NULL, quit, NULL)) != 0){
perror("qiut thread create error!\n");
exit(1);
}
/*记录空闲的套接字描述符(-1为空闲)*/
int i=0;
for(i=0; i<MAX_MEM; i++){
client_fd[i] = -1;
}
while(1)
{
len=sizeof(struct sockaddr);
for(i=0;i<MAX_MEM;i++){
if(client_fd[i]==-1){
break;//若空闲,可进行连接
}
}
/*accept*/
if ((client_fd[i] = accept(sockfd, (struct sockaddr *)&client_sockaddr, &len)) == -1){
perror("Accept error!\n");
exit(1);
}
else printf("Connect success id:%d\n",client_fd[i]);
pthread_t td;
pthread_create(&td, NULL, rcv_mes, (void*)i);// 开一个线程来和 accept 的客户端进行交互
}
return 0;
}
/*退出服务器*/
void *quit(void *arg){
char msg[16];
while(1){
scanf("%s",msg);
if (strcmp("quit",msg) == 0){
printf("Bye...\n");
close(sockfd);
exit(0);
}
}
}
void *rcv_mes(void* arg)
{
int n = (int)arg;
char* ask="Please input you name:\n";
time_t ticks;
char name[20];
int len;
int retval;
int i;
char buf[BUFFER_SIZE];
char buf1[BUFFER_SIZE];
char buf2[BUFFER_SIZE];
memset(name, 0, 20);
write(client_fd[n], ask, strlen(ask));
len=read(client_fd[n],name,20);
if(len>0)
{
name[len]=0;
}
memset(buf,0,BUFFER_SIZE);
strcpy(buf,name);
strcat(buf,"\tWelcome:\0");
for(i=0;i<MAX_MEM;i++)
{
if(client_fd[i] != -1)
{
write(client_fd[i], buf, strlen(buf));
}
}
while(true)
{
memset(buf1,0,BUFFER_SIZE);
if((len=read(client_fd[n],buf1,BUFFER_SIZE))>0)
{
buf1[len]=0;
if(strcmp("bye\n",buf1)==0)
{
memset(buf,0,BUFFER_SIZE);
printf("id:%d quit\n",client_fd[n]);
close(client_fd[n]);
client_fd[n]=-1;
pthread_exit(&retval);
}
ticks=time(NULL);
sprintf(buf2,"%.24s\r\n",ctime(&ticks));
memset(buf, 0, BUFFER_SIZE);
strcpy(buf,name);
strcat(buf,"\t");
strcat(buf,buf2);
strcat(buf,"\t");
strcat(buf,buf1);
for(i=0;i<MAX_MEM;i++)
{
if(client_fd[i] != -1)
{
write(client_fd[i], buf, strlen(buf));
}
}
}
else break;
}
}
Makefile:
OBJS = server.o
CC = gcc
CFLAGS = -w
server : $(OBJS)
$(CC) $(OBJS) -o server -pthread
server.o : server.c
$(CC) $(CFLAGS) -c server.c -o server.o
make clean:
rm -rf *.o server