window下TCP socket编程

1.Socket是什么呢?

 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

2.基于TCP的socket编程的一般步骤如下:

   服务器端:

    1.创建套接字,套接字类型为 SOCK_STREAM    socket()

    2.绑定套接字到一个本地IP地址和端口上  bind();

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

    4.等待客户端请求的到来,当请求到来后,返回一个新的对于这次请求的套接字  accept()

    5.用返回的套接字和客户端进行通信  send()/recv()

    6.返回,等待另一个客户请求。

    7.关闭套接字。

   客户端:
    1.创建套接字  socket()
    2.向服务器发出连接请求  connect()---------对应于服务器端的accept()
    3.和服务器端进行通信  send()/recv()
    4.关闭套接字 closesocket()

下面是基于TCP的Socket编程的简单程序,主要实现的功能时:客户端向服务器端发送请求“hello ,this is client",服务器收到该信息,并回送客户端消息”hello,this is server!"

client.c

/基于TCP(面向连接)的socket编程,分为客户端和服务器端。
//客户端的流程如下:
//(1)创建套接字(socket)
//(2)向服务器发出连接请求(connect)---------对应于服务器端的accept
//(3)和服务器端进行通信(send/recv)
//(4)关闭套接字
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define SOCKPORT 8000
int main(void)
{
	WSADATA wsaData;
	SOCKET socketfd;//套接字描述符
	struct sockaddr_in ser_addr;
	char *sendtos="hello,this is client!\n";
	char recvstr[80];
	int len=sizeof(ser_addr);
	int recvnum;
	if(WSAStartup(MAKEWORD(2,2),&wsaData) !=0)
	{
		printf("error1\n");
		return 0;
	}
	socketfd=socket(AF_INET,SOCK_STREAM,0);
	if(socketfd==INVALID_SOCKET)
	{ 
		printf("error2!\n");
		closesocket(socketfd);
	    WSACleanup();
		 return 0;
	}
	//构建服务器套接字地址
	ser_addr.sin_family=AF_INET;
	ser_addr.sin_port=htons(SOCKPORT);
	ser_addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
	connect(socketfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
	//sendto(socketfd,sendtos,strlen(sendtos),0,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
	send(socketfd,sendtos,strlen(sendtos),0);
    printf("waiting for the response from the server...\n\n");
	//while(1)//进入阻塞状态等待服务器发送响应,并接受(这里要不要用循环)
  // {
		//char recvstr[80];
		//int len=sizeof(ser_addr);
		//recvnum=recvfrom(socketfd,recvstr,80,0,(struct sockaddr *)&ser_addr,&len);
	    recvnum=recv(socketfd,recvstr,80,0);
		if(recvnum>0)
		{
			recvstr[recvnum]='\0';
			printf("The respnse from the server:\n%s\n",recvstr);
		}
   //  }
	closesocket(socketfd);
	WSACleanup();
	return 0;
}

server.c

//tcp,提供可靠的,有连接的数据传输
//服务器端的流程如下:
//(1)创建套接字(socket)
//(2)将套接字绑定到一个本地地址和端口上(bind)
//(3)将套接字设为监听模式,准备接收客户端请求(listen)
//(4)等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)
//(5)用返回的套接字和客户端进行通信(send/recv)
//(6)返回,等待另一个客户请求。
//(7)关闭套接字。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define SOCKPORT 8000
int main(void)
{
	WSADATA wsaData;
	SOCKET sersocket;
	SOCKET sersocket1;
	struct sockaddr_in ser_addr,cli_addr;
	char *sendstr="hello,this is server!\n";
	int len,cli_len;
	if(WSAStartup(MAKEWORD(2,2),&wsaData) !=0)
	{
		printf("error1\n");
		return 0;
	}
	sersocket=socket(AF_INET,SOCK_STREAM,0);
	if(sersocket==INVALID_SOCKET)
	{
		printf("error2!\n");
		return 0;
	}
	//创建套接字地址结构(即本地服务器地址)
	ser_addr.sin_family=AF_INET;//套接字地址结构的地址族
	ser_addr.sin_port=htons(SOCKPORT);
	ser_addr.sin_addr.S_un.S_addr=INADDR_ANY;
	if( bind(sersocket,(struct sockaddr *)&ser_addr,sizeof(ser_addr))<0)
	{
		printf("bind error!\n");
		closesocket(sersocket);
		WSACleanup();
		return 0;
	}
	if(listen(sersocket,20)!=0)
	{
		printf("listen error!\n");
		return 0;
	}
	len=sizeof(ser_addr);
	cli_len=sizeof(cli_addr);
	
	//阻塞等待接受客户端连接
	printf("waiting for the requese from the client...\n\n");
	while(1)循环监听客户端,永远不停止,所以,在本项目中,我们没有心跳包。按ctrl+c退出
	{
		//监听申请的连接
		//用listen()创建套接口并为申请进入的连接建立一个后备日志,然后便可用accept()接受连接了。listen()仅适用于支持连接的套接口,
		//如SOCK_STREAM类型的。套接口s处于一种“变动”模式,申请进入的连接请求被确认,并排队等待被接受。这个函数特别适用于
		//同时有多个连接请求的服务器;如果当一个连接请求到来时,队列已满,那么客户将收到一个WSAECONNREFUSED错误。
		int recvnum;
		char buf[80];
		sersocket1=accept(sersocket,(struct sockaddr *)&cli_addr,&cli_len);//套接字号sersocket在listen()后监听连接
		 if(sersocket1==INVALID_SOCKET)
        {
	         printf("accpt()  failed!\n");
	         closesocket(sersocket);
	         WSACleanup();
	          return 0;
         }
		//recvnum=recvfrom(sersocket1,buf,80,0,(struct sockaddr *)&ser_addr,&len);
		 recvnum=recv(sersocket1,buf,80,0);
		if(recvnum>0)//接收到数据
		{
			buf[recvnum]='\0';
			printf("reveive the request from the client:\n%s\n",buf);
		}
		//sendto(sersocket1,sendstr,strlen(sendstr),0,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
		send(sersocket1,sendstr,strlen(sendstr),0);
	}
	//服务端向客户端发响应
	closesocket(sersocket1);
	closesocket(sersocket);
	WSACleanup();
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值