⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multi_server(linux socket

📁 linux下C++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 + -