Windows下的网络编程(tcp循环并发服务器)

  学了Windows下的网路编程,做了一个小例子试了下手,和Linux下的网路编程感觉总体上差不多,但是细节上,比如说函数的实现还是有些不同。总的结构和Linux差不多,如下图所示:


话不多说,直接上代码,和Linux网络编程一样,我也把socket、bind、listen、accept、connect函数封装在了一个文件中,服务器和客户端是公用的。

/***********socket.h********************/
#ifndef SOCKET_H
#define SOCKET_H

#pragma comment(lib, "ws2_32.lib")
#include <iostream>
#include <string>
#include <Windows.h>

#define SERV_PORT 9000

using namespace std;

extern void tcp_WSA();
extern int  tcp_init();
extern int  tcp_accept(int sfd);
extern int  tcp_connet();

#endif

/***********socket.c********************/
#include "socket.h"

void tcp_WSA()
{
	WSADATA lpWSAD;
	WORD wVer = MAKEWORD(2,2);
	int ret;
	ret = WSAStartup(wVer, &lpWSAD);
	if (ret != 0)
	{
		cout<<"初始化错误"<<endl;
		return;					//初始化错误
	}
	if ( LOBYTE( lpWSAD.wVersion ) != 2 || HIBYTE( lpWSAD.wVersion ) != 2 )
	{
		cout<<WSACleanup( )<<endl;
		return; 
	}
}

int tcp_init()
{
	SOCKET sfd;
	sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sfd == INVALID_SOCKET)
	{
		cout<<"socket create fail"<<endl;
		return -1;
	}

	int ret;
	struct sockaddr_in FAR serveraddr;

	memset(&serveraddr,0,sizeof(struct sockaddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(SERV_PORT);
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

	ret = bind(sfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr));
	if (ret == SOCKET_ERROR)
	{
		cout<<"bind fail"<<endl;
		return -1;
	}

	ret = listen(sfd, 10);
	if (ret == SOCKET_ERROR)
	{
		cout<<"listen fail"<<endl;
		return -1;
	}

	return sfd;
}

int  tcp_accept(int sfd)
{
	SOCKET cfd;
	struct sockaddr_in FAR addr;
	int FAR addrlen = sizeof(struct sockaddr);

	cfd = accept(sfd, (struct sockaddr *)&addr, &addrlen);
	if (cfd == INVALID_SOCKET)
	{
		cout<<"accept fail"<<endl;
		return -1;
	}
	cout<<inet_ntoa(addr.sin_addr)<<" "<<ntohs(addr.sin_port)<<" success connect..."<<endl;

	return cfd;
}

int tcp_connet()
{
	int ret;
	SOCKET sfd;
	sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sfd == INVALID_SOCKET)
	{
		cout<<"socket create fail"<<endl;
		return -1;
	}

	struct sockaddr_in FAR serveraddr;

	memset(&serveraddr, 0,sizeof(struct sockaddr_in));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(SERV_PORT);
	serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");   

	ret = connect(sfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr));   //将sfd连接至指定的服务器网络地址 serveraddr
	if (ret == SOCKET_ERROR)
	{
		cout<<"connect fail"<<endl;
		return -1;
	}

	return sfd;
}

/***********client.c********************/
#include "socket.h"

int main()
{
	tcp_WSA();
	int sfd, ret;
	char ch;
	sfd = tcp_connet();

	while(1)
	{
		cout<<"请输入一个小写字母:";
		cin>>ch;
		ret = send(sfd, &ch, sizeof(ch), 0);
		if (ret == -1)
		{
			cerr<<"send error,please send again"<<endl;
			continue;
		}

		ret = recv(sfd, &ch, sizeof(ch), 0);
		if(ret == -1)
		{
			cerr<<"recv error"<<endl;
			continue;
		}
		cout<<"转换后的字母为:"<<ch<<endl;
	}
	shutdown(sfd, 2);
	closesocket(sfd);
	WSACleanup();
}

/**************server.c******************/
#include "socket.h"

DWORD WINAPI func(LPVOID p)
{
	int cfd = (int)p;
	int ret;
	char ch;
	while(1)
	{
		ret = recv(cfd, &ch, sizeof(ch), 0);
		if(ret == -1)
		{
			cerr<<"xxx下线"<<endl;
			break;
		}

		ch = ch - ('a' - 'A');

		ret = send(cfd, &ch, sizeof(ch), 0);
		if(ret == -1)
		{
			cerr<<"send error"<<endl;
			continue;
		}
	}
	
	return 0;
}

int main()
{
	int ret;
	SOCKET sfd, cfd;
	tcp_WSA();
	sfd = tcp_init();

	while (1)
	{
		cfd = tcp_accept(sfd);

		DWORD thread1Id;
		HANDLE handel1 = CreateThread(NULL, 0, func, (LPVOID) cfd, 0, &thread1Id);
		if (handel1 == false)
		{
			cerr<<"create error"<<endl;
			return -1;
		}
		WaitForSingleObject(handel1, 0);
		CloseHandle(handel1);
	}
	shutdown(cfd, 2);
	closesocket(cfd);
	WSACleanup();
}



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值