网络编程——阻塞模式

1、API详解
(1)int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData)
    为了在应用程序当中调用任何一个Winsock API函数,首先第一件事情就是必须通过WSAStartup函数完成对Winsock服务的初始化。该函数的第一个参数指明程序请求使用的Socket版本,操作系统利用第二个参数返回请求的Socket的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。
(2)socket()
根据指定的地址族、数据类型和协议来分配一个套接口的描述字及其所用的资源。
(3)bind()
将一本地地址与一套接口捆绑。
(4)listen()
创建一个套接口并监听申请的连接。
(5)accept()
在一个套接口接受一个连接。成功返回一个新的套接字描述符。
(6)recv()
从一个套接口接收数据。
(7)send()

向一个已经连接的socket发送数据


2、源码

服务端:

#include <stdio.h>
#include <winsock2.h>  //winsock.h (2种套接字版本)
#include <process.h>   //for beginthread
#pragma comment(lib,"ws2_32.lib") //wsock32.lib 

#define MAX_LISTEN_NUM      5  //最多可同时监听的客户连接数
#define CONNECT_PORT        1027
#define CONNECT_IP          "127.0.0.1"
#define DEFAULT_BUFF_SIZE   512

unsigned int WINAPI ClientThread(void* lpParam)
{
	//当前线程中保存指定的客户端Socket

	SOCKET sClient = (SOCKET)lpParam;
	char    szBuff[DEFAULT_BUFF_SIZE] ={0};
	int     nRes;
	int     nLeft;  //剩余字节数,用于发送
	int     nIndex; //送信Buff下标

	printf("******Start a Client: ThreadID=%d, Socket=%d******\n",::GetCurrentThreadId(),sClient);
	while(true)
	{
		printf("--- start recv message(ThreadID:%d)\n",::GetCurrentThreadId());
		memset(szBuff, 0, sizeof(szBuff) );
		nRes = recv(sClient, szBuff, sizeof(szBuff), 0);  //这里会阻塞
		//当拔掉设备网线的时候,recv并不会发生变化,仍然阻塞,如果在这个拔网线阶段,socket被关掉了,后果可能就是recv永久的阻塞了。
		if( nRes == 0 )  //socket被正常关闭时,返回0。
		{
			printf("-XXX Client Has Closed.\n");
			break;
		}
		else if(nRes == SOCKET_ERROR )
		{
			printf("-XXX ClientThread recv Failed: %d\n",WSAGetLastError());
			break;
		}
		//获取到了指定的字节数
		szBuff[nRes] = '\0';
		printf("-recved message(ThreadID:%d):(%d): %s\n",::GetCurrentThreadId(),nRes,szBuff);
		//告诉客户端收到了发送的数据
		printf("-send message:(%d): %s\n",nRes,szBuff);
		nLeft  = nRes; //指示收到了多少字节
		nIndex = 0;
		while( nLeft>0 )
		{
			nRes = send(sClient, &szBuff[nIndex], nLeft, 0);
			if( nRes == 0 )
			{
				printf("-send message OK\n");
				break;
			}
			else if( nRes == SOCKET_ERROR )
			{
				printf("-XXX ClientThread send Failed: %d\n",WSAGetLastError());
				break;
			}
			nLeft  -= nRes;
			nIndex += nRes;
		}//while(nLeft>0)
	}//while(true)
	printf("******Close a Client******\n");
	return 0;
}

int main()
{
	WSAData     wsdata;
	SOCKET      sockServer;
	SOCKET      sockRecvClient;
	SOCKADDR_IN addrServer;
	SOCKADDR_IN addrRecvClient;
	int         addrlenClient;
	HANDLE      hThread;         //处理客户连接用的线程Handle
	UINT        nThreadID;
	int         nError       = -1;

	printf(">>>>>>>>server
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值