server.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include <arpa/inet.h>
#include<pthread.h>
#define SERV_PORT 5001
struct cli_msg
{
int newfd;
struct sockaddr_in cin;
};
void cli_data_handle(void *arg);
int main()
{
int fd = -1;
struct sockaddr_in sin;
/*创建socket*/
if((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(1);
}
int b_reuse = 1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
/*绑定*/
/*填充struct sockaddr_in*/
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(SERV_PORT);//网络字节序的端口号
sin.sin_addr.s_addr = INADDR_ANY;
/*绑定*/
if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("bind");
exit(1);
}
/*调用listen()把主动套接字变成被动套接字*/
if(listen(fd,5) < 0)
{
perror("listen");
exit(1);
}
printf("Server starting ok\n");
int newfd = -1;
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
pthread_t tid;
while (1)
{
/*阻塞等待客户端连接请求*/
if(newfd = accept(fd,(struct sockaddr *)&cin,&addrlen) < 0)
{
perror("accept");
exit(1);
}
/*获取刚建立连接的socket的客户端的ip地址和端口*/
char ipv4_addr[16];
if(!inet_ntop(AF_INET,(void *)&cin.sin_addr.s_addr,ipv4_addr,sizeof(cin)))
{
perror("inet_ntop");
exit(1);
}
printf("Client(%s:%d) is connected\n",ipv4_addr,htons(cin.sin_port));
pthread_create(&tid,NULL,(void *)cli_data_handle,(void *)&newfd);
}
close(fd);
return 0;
}
void cli_data_handle(void * arg)
{
int newfd = *(int *)arg;
printf("handler pthread: newfd = %d\n",newfd);
/*读写*/
int res = -1;
char buf[BUFSIZ];
while (1)
{
bzero(buf,BUFSIZ);
do
{
res = read(newfd,buf,BUFSIZ-1);
} while (res < 0 && EINTR == errno);
if(res < 0)
{
perror("read");
exit(1);
}
if(!res)//对方已关闭
{
break;
}
printf("Recv data: %s\n",buf);
if(strcmp(buf,"q\n") == 0)//用户输入了q字符退出
{
printf("Client(fd = %d) is exiting\n",newfd);
break;
}
}
close(newfd);
}
client.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include <arpa/inet.h>
#include<pthread.h>
#define SERV_PORT 5001
void usage(char *s)
{
printf("\n%s serv_ip serv_port",s);
printf("\n\t serv_ip: server ip address");
printf("\n\t serv_port: server port(>5000)\n\n");
}
int main(int argc,char **argv)
{
struct sockaddr_in sin;
int fd = -1;
int port = -1;
int res;
if(argc != 3)
{
usage(argv[0]);
exit(1);
}
/*创建socket*/
if((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(1);
}
port = atoi(argv[2]);
if(port < 5000)
{
usage(argv[0]);
exit(1);
}
/*连接服务器*/
/*绑定*/
/*填充struct sockaddr_in*/
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);//网络字节序的端口号
//sin.sin_addr.s_addr = inet(SERV_IP_ADDR);
if(inet_pton(AF_INET,argv[1],(void *)&sin.sin_addr.s_addr) != 1)
{
perror("inet_pton");
exit(1);
}
if(connect(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("connect");
exit(1);
}
/*读写*/
char buf[BUFSIZ];
while (1)
{
bzero(buf,BUFSIZ);
if(fgets(buf,BUFSIZ-1,stdin) == NULL)
{
continue;
}
if((res = write(fd,buf,strlen(buf))) == -1)
{
perror("write");
exit(1);
}
if(strcmp(buf,"q\n") == 0)//用户输入了q字符退出
{
printf("Client is exiting\n");
break;
}
}
close(fd);
}