📄 multi_server(linux socket
字号:
//multi_thread_server.c
#include <netinet/in.h> // for sockaddr_in
#include <sys/types.h> // for socket
#include <sys/socket.h> // for socket
#include <stdio.h> // for printf
#include <stdlib.h> // for exit
#include <string.h> // for bzero
#include <pthread.h>
#include <sys/errno.h> // for errno
#define HELLO_WORLD_SERVER_PORT 6666
#define LENGTH_OF_LISTEN_QUEUE 20
#define BUFFER_SIZE 4096
#define THREAD_MAX 5
#define MAX_SU_DATA_LEN 302
#define GN_EVT_STARTTIME 14
#define GN_EVT_MSU 4
#define GN_EVT_TRANS_ALARM 5
#define GN_EVT_SIGNAL_ALARM 6
#define GN_EVT_SIGNAL_ERROR 7
#define GN_EVT_SEQ_HEADER 10
#define GN_EVT_DATA_LOST 0
#define GN_EVT_OVERFLOW 2
#define GN_EVT_TRIGGER_EVENT 11
typedef struct _HeadMsg
{
unsigned short length;
unsigned char type;
}HeadMsg, *PHeadMsg;
unsigned long pcnt = 0;
unsigned char cPendingBuf[0x20000];
long iPendingLen = 0;
int analyseTcpStream(char *buff, const int iLen);
void * pthread_work(void *data)
{
int new_server_socket = (int)data;
char buffer[BUFFER_SIZE];
bzero(buffer, BUFFER_SIZE);
strcpy(buffer,"Hello,World! 从服务器来!");
strcat(buffer,"\n"); //C语言字符串连接
printf("\nSocket Num: %d \t %s",new_server_socket, buffer);
//关闭与客户端的连接
close(new_server_socket);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
//设置一个socket地址结构server_addr,代表服务器internet地址, 端口
struct sockaddr_in server_addr;
bzero(&server_addr,sizeof(server_addr)); //把一段内存区的内容全部设置为0
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htons(INADDR_ANY);
server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
//创建用于internet的流协议(TCP)socket,用server_socket代表服务器socket
int server_socket = socket(AF_INET,SOCK_STREAM,0);
if( server_socket < 0)
{
printf("Create Socket Failed!");
exit(1);
}
//把socket和socket地址结构联系起来
if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))
{
printf("Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT);
exit(1);
}
//server_socket用于监听
if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) )
{
printf("Server Listen Failed!");
exit(1);
}
int i;
while(1) //服务器端要一直运行
{
//定义客户端的socket地址结构client_addr
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
//接受一个到server_socket代表的socket的一个连接
//如果没有连接请求,就等待到有连接请求--这是accept函数的特性
//accept函数返回一个新的socket,这个socket(new_server_socket)用于同连接到的客户的通信
//new_server_socket代表了服务器和客户端之间的一个通信通道
//accept函数把连接到的客户端信息填写到客户端的socket地址结构client_addr中
int new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);
if ( new_server_socket < 0)
{
printf("Server Accept Failed!\n");
break;
}
pthread_t child_thread;
pthread_attr_t child_thread_attr;
pthread_attr_init(&child_thread_attr);
pthread_attr_setdetachstate(&child_thread_attr,PTHREAD_CREATE_DETACHED);
if( pthread_create(&child_thread,&child_thread_attr,pthread_work, (void *)new_server_socket) < 0 )
printf("pthread_create Failed : %s\n",strerror(errno));
}
//关闭监听用的socket
close(server_socket);
return 0;
}
/*
函数: analyseTcpStream
说明: 这个函数分析TCP Stream,分解出PCU API格式的数据包(可能一次分解出多个)
参数:
buff 收到的TCP Stream
iLen TCP Stream长度
packLnk 数据包链表
返回: 数据包个数
*/
int analyseTcpStream(char *buff, const int iLen)
{
int dPacketNum=0;
int iPendingPtr=0;
int bDoneFlag = 0;
int packlen;
unsigned char *pbyte, type;
if((iLen+iPendingLen) > 0x20000)
{
printf("packet isweyrh too length:%d", iLen);
return 0;
}
memcpy (&cPendingBuf[iPendingLen], buff, iLen);
iPendingLen += iLen;
while (!bDoneFlag && (iPendingLen > 8))
{ // Head enough
pbyte = &cPendingBuf[iPendingPtr];
packlen = *pbyte + *(pbyte+1) * 0x100;
type = *(pbyte+2);
// Check: length valid?
if (packlen > 2048|| packlen < 4)
{ /* Invalid packet, close socket */
iPendingLen = 0;
bDoneFlag = 1;
sprintf(errmsg,"Recv data error ,Invalid packet: recvlen:%d, cuntlen:%d, packlen:%d, type:%d",
iLen, iPendingLen, packlen, pEvt->event_h.type);
OutputDebugString(errmsg);
continue;
}
if (iPendingLen < packlen)
{ /* packet no finished */
bDoneFlag = 1;
continue;
}
switch (type)
{
case GN_EVT_MSU:
int lkId;
lkId = pEvt->msu.msu_h.timeSlot;
pcnt++;
sprintf (errmsg, "\r[%u], packlen=%d\t", pcnt, packlen);
printf(errmsg);
dPacketNum++;
break;
case GN_EVT_STARTTIME:
dPacketNum++;
break;
case GN_EVT_TRANS_ALARM:
break;
case GN_EVT_SIGNAL_ALARM:
break;
default:
sprintf(errmsg,"Recv data error: recvlen:%d, cuntlen:%d, packlen:%d, type:%d",
iLen, iPendingLen, packlen, pEvt->event_h.type);
OutputDebugString(errmsg);
bDoneFlag = 1;
iPendingLen = 0;
break;
} // switch (type)
iPendingLen -= packlen;
iPendingPtr += packlen;
} // while
if (iPendingLen > 0 && iPendingLen < 2048)
{
memcpy (tmpBuf, &cPendingBuf[iPendingPtr], iPendingLen);
memcpy (cPendingBuf, tmpBuf, iPendingLen);
}
else if (iPendingLen != 0)
{
sprintf(errmsg,"Recv data error: recvlen:%d, cuntlen:%d, packlen:%d, type:%d",
iLen, iPendingLen, packlen, pEvt->event_h.type);
OutputDebugString(errmsg);
iPendingLen = 0;
}
return dPacketNum;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -