首页 > 代码库 > TCP的Socket技术之服务器端

TCP的Socket技术之服务器端

    XX:那飘过的100~_~{2014/10/02 16:12}

    流式套接字(SOCK_STREAM):提供面向连接、可靠的数据传输服务、数据无差错、无重复的发送、且按发送顺序接受。程序的设计思路

    服务器端:

    流程:WSAStartup()->socket()->bind()->listen()->accept()->send()

    (1)创建套接字

    (2)将套接字绑定到一个本地地址和端口上

    (3)将套接字设为监听模式,准备接受客户端的请求

    (4)等待客户端请求的到来,当请求到来后,接受连接请求,返回一个对应与此次连接的套接字

    (5)用返回的套接字与客户端进行通讯

    (6)返回,等待另一个客户端的连接请求

    (7)关闭套接字

// socketTcp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "tchar.h"

#pragma comment(lib,"wsock32.lib")
#include <stdio.h>
#include <winsock2.h>

#define MAX_SER 10
#define HOST_PATH 256
#define HOSTNAME_SIZE HOST_PATH

char hostName[MAX_PATH]={0};
unsigned short maxService;
unsigned short port;


void Service(LPVOID lpv);
int LoopControl(SOCKET llistenfd,int isMultiTasking);
void initial();												
int initSockets(void);											//初始化Windows Socket

int main(int argc, char * argv[])  
{
	SOCKET listenFd;			             
	struct sockaddr_in serverAddr;		
	int err;

	initial();
	initSockets();
	
	//创建socket
	listenFd=socket(PF_INET,SOCK_STREAM,0);						
	if(listenFd==INVALID_SOCKET){
		printf("error:out of socket resource \n");
		return 1;		
	}

	//bind本机的端口
	serverAddr.sin_family=PF_INET;														//协议类型是INET
	serverAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);									//本机IP
	serverAddr.sin_port=htons(port);													//绑定端口为5054

	err=bind(listenFd,(const struct sockaddr *)&serverAddr,sizeof(serverAddr));			
	if(err==INVALID_SOCKET){
		printf("error: unable to bind socket \n");
		return 1;
	}
	
	//listen 监听端口
	err=listen(listenFd,3);				
	if(err==INVALID_SOCKET){
		printf("error: listen socket failed \n");
		return 1;
	}
	printf("listen......");

	LoopControl(listenFd,1);
	printf("server is down \n");
	WSACleanup();

	return 0;
}

void initial()
{
	maxService=3;
	port=5054;
}

 /*
  *	Winsock服务初始化
 */
int initSockets(void)
{
	WSADATA wsaData;
	WORD sockVersion;                                              //typedef unsigned short WORD(16)
	int err;
	sockVersion=MAKEWORD(2,2);
	err=WSAStartup(sockVersion,&wsaData);						  
	if(err!=0)
	{
		printf("error %d :winsock not avaliable\n",err);
	}
	printf("environemnt invaild success.....\n");
	return 0;
}

/*
** 等待客户端的连接
*/
int LoopControl(SOCKET listenfd,int isMultiTasking){
	SOCKET acceptfd;
	struct sockaddr_in clientAddr;				//客户端地址信息
	int err;
	int serverNum=0;
	HANDLE handles[MAX_SER];
	int nSize;
	nSize=sizeof(clientAddr);
	int myID;
	
	//存在固定的次数[服务次数小于最大服务次数]
	while(serverNum<maxService)
	{
		acceptfd=accept(listenfd,(struct sockaddr *)&clientAddr,&nSize);			//接收客户连接的准备
		if(acceptfd==INVALID_SOCKET)
		{
			printf("error:accept failed \n");
			return 1;
		}
		printf("accepted connection from client at %s \n",inet_ntoa(clientAddr.sin_addr));
		if(isMultiTasking)
		{
			handles[serverNum]=CreateThread(NULL,1000,(LPTHREAD_START_ROUTINE)Service,(LPVOID)acceptfd,0,(unsigned long *)&myID);
		}
		else
		{
			Service((LPVOID)acceptfd);
		}
		serverNum++;
	}
	if(isMultiTasking)
	{
		err=WaitForMultipleObjects(maxService,handles,TRUE,INFINITE);
		printf("last thread to finish was thread # %d \n",err);
	}
	return 0;
}

			
/*
*接收客户端的数据,AND向客户端发送数据
*/			
void Service(LPVOID lpv){		
	SOCKET acceptfd=(SOCKET)lpv;
	const char *msg="message have recived";
	char response[4096];
	memset(response,0,sizeof(response));
	
	while(acceptfd!=SOCKET_ERROR)
	{
		int result=recv(acceptfd,response,sizeof(response),0);				//接受客户机的数据
		if(result>0)
		{
			printf("from client: %s ",response);
			send(acceptfd,msg,strlen(msg)+1,0);
		}

	}
	closesocket(acceptfd);
}

    在浏览器中输入本地ip:5054,查看运行效果。或者使用netstat -a查看端口状态


    

TCP的Socket技术之服务器端