有个朋友因为工作需要让我写一个tcpserver demo给他,于是有了下面这段代码,本程序包含了端口复用,进程异常退出问题的修复,希望对大家有所帮助!
#include<stdlib.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netdb.h>
#include<string.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <signal.h>
#define PORT 3301
#define HEARTBEATPORT 3302
//发送数据线程
void *SendThreadpro(void *args)
{
struct sockaddr_in server;
struct sockaddr_in client;
int len;
int port;
int listend;
int connectd;
int sendnum;
int opt;
int recvnum;
char send_buf[2048];
char recv_buf[2048];
port= PORT;
memset(send_buf,'\0',2048);
memset(recv_buf,'\0',2048);
opt = SO_REUSEADDR;
if (-1==(listend=socket(AF_INET,SOCK_STREAM,0)))
{
perror("create listen socket error\n");
pthread_exit(0);
return NULL;
}
setsockopt(listend,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
int val = 1;
if (setsockopt(listend, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1)
{
pthread_exit(0);
return NULL;
}
#if 0
int reuse0 = 1;
if (0 != setsockopt(listend, SOL_SOCKET, SO_REUSEPORT, (char *)&reuse0, sizeof(reuse0)))
{
pthread_exit(0);
return NULL;
}
#endif
memset(&server,0,sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
if (-1==bind(listend,(struct sockaddr *)&server,sizeof(struct sockaddr)))
{
error("bind error\n");
pthread_exit(0);
return NULL;
}
if (-1==listen(listend, 20))
{
perror("listen error\n");
pthread_exit(0);
return NULL;
}
while (1)
{
if (0 > (connectd=accept(listend,(struct sockaddr*)&client,&len)))
{
perror("create connect socket error\n");
continue;
}
while (1)
{
memset(send_buf,'\0',2048);
memset(recv_buf,'\0',2048);
if (0>(recvnum = recv(connectd,recv_buf,sizeof(recv_buf),0)))
{
perror("recv error\n");
shutdown(connectd, 2);
close(connectd);
break;
}
printf ("the message from the client is: %s\n",recv_buf);
sprintf(send_buf, "hello nihao1 send packet");
if (0 > send(connectd,send_buf,strlen(send_buf),0))
{
perror("recv error\n");
shutdown(connectd, 2);
close(connectd);
break;
}
usleep(5000);
}
usleep(5000);
}
close(connectd);
close(listend);
pthread_exit(0);
}
//发送心跳函数
void *SendThreadHeartBeatpro(void *args)
{
struct sockaddr_in server;
struct sockaddr_in client;
int len;
int port;
int listend;
int connectd;
int sendnum;
int opt;
int recvnum;
char send_buf[2048];
char recv_buf[2048];
port= HEARTBEATPORT;
memset(send_buf,'\0',2048);
memset(recv_buf,'\0',2048);
opt = SO_REUSEADDR;
if (-1==(listend=socket(AF_INET,SOCK_STREAM,0)))
{
perror("create listen socket error\n");
pthread_exit(0);
return NULL;
}
setsockopt(listend,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
int val = 1;
if (setsockopt(listend, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1)
{
pthread_exit(0);
return NULL;
}
#if 0
int reuse0 = 1;
if (0 != setsockopt(listend, SOL_SOCKET, 15, (char *)&reuse0, sizeof(reuse0)))
{
pthread_exit(0);
return NULL;
}
#endif
memset(&server,0,sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
if (-1==bind(listend,(struct sockaddr *)&server,sizeof(struct sockaddr)))
{
error("bind error\n");
pthread_exit(0);
return NULL;
}
if (-1==listen(listend, 20))
{
perror("listen error\n");
pthread_exit(0);
return NULL;
}
while (1)
{
if (-1==(connectd=accept(listend,(struct sockaddr*)&client,&len)))
{
perror("create connect socket error\n");
continue;
}
while (1)
{
memset(send_buf,'\0',2048);
memset(recv_buf,'\0',2048);
if (0>(recvnum = recv(connectd,recv_buf,sizeof(recv_buf),0)))
{
perror("recv error\n");
close(connectd);
break;
}
printf ("the message from the client is: %s\n",recv_buf);
sprintf(send_buf, "hello nihao2 HeartBeat");
if (0 > send(connectd,send_buf,strlen(send_buf),0))
{
perror("recv error\n");
shutdown(connectd, 2);
close(connectd);
break;
}
usleep(5000);
}
usleep(5000);
}
close(connectd);
close(listend);
pthread_exit(0);
}
void SendThread()
{
pthread_t mid1;
if (pthread_create(&mid1, NULL, SendThreadpro,NULL)) //普通包
{
return;
}
pthread_detach(mid1);
}
void SendThreadHeartBeatThread()
{
pthread_t mid2;
if (pthread_create(&mid2, NULL, SendThreadHeartBeatpro,NULL)) //心跳
{
return;
}
pthread_detach(mid2);
}
//主进程
int main(int argc,char** argv)
{
signal(SIGPIPE, SIG_IGN); //避免shutdown后进程退出
signal(SIGCHLD,SIG_IGN);
SendThread();
SendThreadHeartBeatThread();
printf("send data start!!!\n");
while (1)
{
sleep(1);
}
return 0;
}