#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>
#include<pthread.h>
int tcp_init(const char* ip, int port) //用于初始化
{
int sfd = socket(AF_INET, SOCK_STREAM, 0); //首先建立一个Socket,向系统申请
if(sfd == -1)
{
perror("Socket error\n");
exit(1);
}
struct sockaddr_in serveraddr;
memset( &serveraddr, 0, sizeof(struct sockaddr) );
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
//将主机的无符号短整形数转换成网络字节顺序。hostshort:主机字节顺序表达的16位数
serveraddr.sin_addr.s_addr = inet_addr(ip); //或者INADDR_ANY
//将新的socket和制定的ip、port绑定
if(bind(sfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr)) == -1)
{
perror("Bind Error");
close(sfd);
exit(-1);
}
if(listen(sfd, 10) == -1) //监听它 最大连接数为10
{
perror("Listen error");
close(sfd);
exit(-1);
}
return sfd;
}
int tcp_accept(int sfd)
{
struct sockaddr_in clientaddr;
memset(&clientaddr, 0, sizeof(struct sockaddr) );
unsigned int addrlen = sizeof(struct sockaddr);
int new_fd = accept(sfd, (struct sockaddr*)&clientaddr, &addrlen);
//sfd接受客户端的连接,创建新的socket为new_fd, 将请求连接的客户端IP
//port保存在结构体clientaddr中
if(new_fd == -1)
{
perror("accept error");
close(sfd);
exit(-1);
}
printf("%s %d success connect...\n", inet_ntoa(clientaddr.sin_addr),
ntohs(clientaddr.sin_port));
//inet_ntoa:函数功能:将网络地址转换成“.”点隔的字符串格式。
return new_fd;
}
void signalhandler(void)
{
sigset_t sigSet;
sigemptyset(&sigSet);
sigaddset(&sigSet,SIGINT);
sigaddset(&sigSet,SIGQUIT);
sigprocmask(SIG_BLOCK,&sigSet,NULL);
}
typedef struct{
int sfd;
int cfd;
}tcp_info;
void* pthread_send(void *arg)
{
tcp_info *temp;
temp = ( tcp_info *)arg;
char buf[128];
while(1)
{
memset(buf, 0, sizeof(buf));
scanf("%s",buf);
if(send(temp->cfd, buf, 128, 0) == -1)
{
perror("send");
close(temp->cfd);
close(temp->sfd);
exit(-1);
}
sleep(1);
}
}
void* pthread_recv(void *arg)
{
char buf[128] = {0};
memset(buf, 0, sizeof(buf));
tcp_info *temp;
temp = ( tcp_info *)arg;
while(1)
{
if(recv(temp->cfd, buf, sizeof(buf), 0 ) == -1)
{
perror("recv");
close(temp->cfd);
close(temp->sfd);
exit(-1);
}
printf("\n");
puts(buf);
}
}
int main(int argc,char **argv)
{
int ret_send;
int ret_recv;
pthread_t id1;
pthread_t id2;
if(argc < 3)
{
printf("usage:./servertcp ip port \n");
exit(-1);
}
signalhandler();
int sfd = tcp_init(argv[1], atoi(argv[2]));
//atoi:把字符串转化成整形的函数,例如atoi(“123”) = 123
//这里也可以这样写: int sfd = tcp_init("192.168.0.164",8888);
int cfd = tcp_accept(sfd);
tcp_info *info;
info = (tcp_info*)malloc(sizeof(tcp_info));
info->sfd = sfd;
info->cfd = cfd;
ret_send = pthread_create(&id1, NULL, pthread_send, (void*)info);
ret_recv = pthread_create(&id2, NULL, pthread_recv, (void*)info);
pthread_join(id1, NULL);
pthread_join(id2, NULL);
close(cfd);
close(sfd);
return 0;
}