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

📄 sock_common.h

📁 实现多线程聊天室
💻 H
字号:


#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

#define MAX_LINE_SIZE	1024
#define INIT_READBUFFER(B)  B.read_count = 0

typedef struct ReadBuffer_t
{
	int read_count;
	char *read_ptr;
	char read_buf[MAX_LINE_SIZE];
} ReadBuffer;

/***************************************************************************************************************
 sockerror 用来输出网络函数的错误信息
***************************************************************************************************************/
void sockerror(const char *format, ...)
{
	int errno;
	va_list	args;

	va_start(args, format);
	fprintf(stderr, format, args);
	va_end(args);

	errno = WSAGetLastError();

	switch (errno)
	{
		case WSAEADDRINUSE:
			fprintf(stderr,"WSAEADDRINUSE:The specified address is already in use.");
			break;
		case WSAEADDRNOTAVAIL:
			fprintf(stderr,"WSAEADDRNOTAVAIL:The specified address is not available from the local machine.");
			break;
		case WSAEAFNOSUPPORT:
			fprintf(stderr,"WSAEAFNOSUPPORT:Addresses in the specified family cannot be used with this socket.");
			break;
		case WSAECONNREFUSED:
			fprintf(stderr,"WSAECONNREFUSED:The attempt to connect was forcefully rejected.");
			break;
		case WSAEDESTADDRREQ:
			fprintf(stderr,"WSAEDESTADDRREQ:A destination address is required.");
			break;
		case WSAEFAULT:
			fprintf(stderr,"WSAEFAULT:The lpSockAddrLen argument is incorrect.");
			break;
		case WSAEINVAL:
			fprintf(stderr,"WSAEINVAL:The socket is already bound to an address.");
			break;
		case WSAEISCONN:
			fprintf(stderr,"WSAEISCONN:The socket is already connected.");
			break;
		case WSAEMFILE:
			fprintf(stderr,"WSAEMFILE:No more file descriptors are available.");
			break;
		case WSAENETUNREACH:
			fprintf(stderr,"WSAENETUNREACH:The network cannot be reached from this host at this time.");
			break;
		case WSAENOBUFS:
			fprintf(stderr,"WSAENOBUFS:No buffer space is available. The socket cannot be connected.");
			break;
		case WSAENOTCONN:
			fprintf(stderr,"WSAENOTCONN:The socket is not connected.");
			break;
		case WSAENOTSOCK:
			fprintf(stderr,"WSAENOTSOCK:The descriptor is a file, not a socket.");
			break;
		case WSAETIMEDOUT:
			fprintf(stderr,"WSAETIMEDOUT:The attempt to connect timed out without establishing a connection. ");
			break;
		default:
			fprintf(stderr,"WSAEError: Unknown! ");
			break;	
	}
	fprintf(stderr,"\n");
}


/***************************************************************************************************************
 readline 用来从网络中读取一行,采用一次读一个字符的方式
 ***************************************************************************************************************/
int ReadLine1(SOCKET s,char FAR *buf,int max_len)
{
	char c,*ptr;
	int n,rc;

	ptr = buf;
	for(n = 1;n < max_len;n++)
	{
		rc = recv(s,&c,1,0);
		if(rc == 1)
		{
			*ptr++ = c;
			if(c == '\n')
				break;
		}
		else		// EOF or SOCKET_ERROR
		{
			if(n==1)   // no data read
				return rc;
			else
				break;
		}
	}

	*ptr = 0;
	return n;
}


/***************************************************************************************************************
  ReadLine 用来从网络中读取一行,先将数据读取到Buffer中,再从Buffer中读取一行
 ***************************************************************************************************************/

static int my_read(SOCKET s,char *ptr,ReadBuffer *pRB)
{
	if( pRB->read_count <= 0)
	{
		pRB->read_count = recv(s,pRB->read_buf,MAX_LINE_SIZE,0);
		if(pRB->read_count <= 0)		// EOF or SOCKET_ERROR
			return pRB->read_count;
		
		pRB->read_ptr = pRB->read_buf;
	}

	pRB->read_count--;
	*ptr = *pRB->read_ptr++;
	return 1;
}

int ReadLine(SOCKET s,char FAR *buf,int max_len,ReadBuffer *pRB)
{
	char c,*ptr;
	int n,rc;

	ptr = buf;
	for(n = 1;n < max_len;n++)
	{
		rc = my_read(s,&c,pRB);
		if(rc == 1)
		{
			*ptr++ = c;
			if(c == '\n')
				break;
		}
		else		// EOF or SOCKET_ERROR
		{
			if(n==1)  // no data read
				return 0;
			else
				break;
		}
	}

	*ptr = 0;
	return n;
}

int Read(SOCKET s,char FAR *buf,int n,ReadBuffer *pRB)
{
	int rc;
	if(pRB->read_count > 0)
	{
		rc = (pRB->read_count < n) ? pRB->read_count:n;
		memcpy(buf,pRB->read_ptr,rc);
		pRB->read_count -= rc;
		pRB->read_ptr += rc;
		return rc;
	}
	rc = recv(s,buf,n,0);
	return rc;
}

/***************************************************************************************************************
  ReadN 用来从网络中读取n个字节
 ***************************************************************************************************************/
int ReadN(SOCKET s,char FAR *buf,int n,ReadBuffer *pRB)
{
	int count = 0;
	int rc;
	
	if(pRB->read_count > 0)
	{
		rc = (pRB->read_count < n) ? pRB->read_count:n;
		memcpy(buf,pRB->read_ptr,rc);
		pRB->read_count -= rc;
		pRB->read_ptr += rc;
		count = rc;
	}

	while(count < n)
	{
		rc = recv(s,buf + count,n - count,0);
		if(rc <= 0)
			break;
		count += rc;
	}

	return count;
}

/***************************************************************************************************************
  WriteN 用来从网络中写取n个字节
 ***************************************************************************************************************/
int WriteN(SOCKET s,char FAR *buf,int n)
{
	int count = 0;
	int sc;
	while(count < n)
	{
		sc = send(s,buf + count,n - count,0);
		if(sc < 0)
			return sc;
		if(sc == 0)
			Sleep(100);
		count += sc;
	}

	return count;
}

/***************************************************************************************************************
 Constructsockaddr 用来从根据地址strAddr和端口strPort自动构造好一个地址机构
 他会自动判断strAddr是域名还是IP地址,然后进行相应转换
 ***************************************************************************************************************/
int ConstructSockaddr(SOCKADDR_IN* paddr_in,char * strAddr,char * strPort)
{
	unsigned short port;
	struct hostent* phostent;

	port = atoi(strPort);
	if (port == 0)
		return 0;

	paddr_in->sin_family = AF_INET;
	paddr_in->sin_port = htons(port);   
	paddr_in->sin_addr.s_addr = inet_addr(strAddr);
	
	if(paddr_in->sin_addr.s_addr != INADDR_NONE)
		return 1;

	phostent = gethostbyname(strAddr);
	if (phostent == NULL)
	{
		sockerror("Resove name %s error!",strAddr);
		return 0;
	}

	paddr_in->sin_addr = *((IN_ADDR*) phostent->h_addr);
	if(paddr_in->sin_addr.s_addr != INADDR_NONE)
		return 1;
	
	return 0;
}



















⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -