[网络编程]_[初级]_[Windows网络编程之搭建服务器和客户端]

网上很多文章对于Socket的来龙去脉有如教科书一般的精准。但是涉及具体编程技术就往往被VC等集成开发环境所毒害了,把Windows SDK、Socket、多线程、DLL以及编译链接等等技术搅合在一起煮成一锅夹生饭。


既然要学习Socket,就应该用最简单直白的方式把Socket的几个使用要点讲出来。我认为程序员最关心的有以下几点,按照优先级排列如下:

1.         Socket的机制是什么?

2.         用C/C++写Socket需要什么头文件、库文件、DLL,它们可以由谁提供,安装后一般处于系统的哪个文件夹内?

3.         编写Socket程序需要的编程基础是什么?

4.         Socket库内最重要的几个函数和数据类型是什么?

5.         两个最简单的例子程序;

6.         一个贴近应用的稍微复杂的Socket应用程序。


一.Socket机制

Socket(套接字)是BSD提供的网络应用编程界面(API),Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。现在它已经是网络编程中的标准。

    Socket是一种特殊的进程间通信方式,不同机器上的进程都可以使用这种方式进行通信,网络中的数据传输是一种I/O操作。Socket也是一种文件描述符,它代表了一个通信管道的一个端点。read,write,close操作可应用于Socket描述符。在socket类型的文件描述符上,可以完成建立连接,数据传输等操作。常用的Socket类型有两种:

流式Socket-SOCK_STREAM,提供面向连接的Socket

数据报式Socket-SOCK_DGRAM,提供面向无连接的Socket


Socket可以支持数据的发送和接收,它会定义一种称为套接字的变量,发送数据时首先创建套接字,然后使用该套接字的sendto等方法对准某个IP/端口进行数据发送;接收端也首先创建套接字,然后将该套接字绑定到一个IP/端口上,所有发向此端口的数据会被该套接字的recv等函数读出。如同读出文件中的数据一样。

二.所需的头文件、库文件和DLL


对于目前使用最广泛的Windows Socket2.0版本,所需的一些文件如下(以安装了VC6为例说明其物理位置):

(1)        头文件winsock2.h,通常处于C:"Program Files"Microsoft Visual Studio"VC98"INCLUDE;查看该头文件可知其中又包含了windows.h和pshpack4.h头文件,因此在windows中的一些常用API都可以使用;

(2)         库文件Ws2_32.lib,通常处于C:"Program Files"Microsoft Visual Studio"VC98"Lib;

(3)         DLL文件Ws2_32.dll,通常处于C:"WINDOWS"system32,这个是可以猜到的


三 实例


服务器:

test_socket_server.cpp

#include <stdio.h>
#include <WinSock2.h>
#include <inaddr.h>
#include <Windows.h>

void ServerSocket()
{
	 //初始化WSA 
	WORD sockVersion = MAKEWORD(2,2);  
    WSADATA wsaData;  
    if(WSAStartup(sockVersion, &wsaData)!=0)  
    {  
        return ;  
    }  
  
    //创建套接字  
    SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
    if(slisten == INVALID_SOCKET)  
    {  
        printf("socket error !");  
        return ;  
    }  
  
    //绑定IP和端口  
    sockaddr_in sin;  
    sin.sin_family = AF_INET;  
    sin.sin_port = htons(8888);  
    sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");   
    if(bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)  
    {  
        printf("bind error !");  
    }  
  
    //开始监听  
    if(listen(slisten, 5) == SOCKET_ERROR)  
    {  
        printf("listen error !");  
        return ;  
    }  
  
    //循环接收数据  
    SOCKET sClient;  
    sockaddr_in remoteAddr;  
    int nAddrlen = sizeof(remoteAddr);  
    char revData[255];  
	printf("等待连接...\n");  
    sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);   
    while (true)  
    {  
        
        if(sClient == INVALID_SOCKET)  
        {  
            printf("accept error !");  
            continue;  
        }  
        //printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));  
          
        //接收数据
		 printf("接受数据:\n");    
        int ret = recv(sClient, revData, 255, 0);         
        if(ret > 0)  
        {  
            revData[ret] = 0x00;  
            printf(revData); 
			printf("\n"); 
        }  

        //发送数据  
        char * sendData = "你好,TCP客户端!\n";  
       send(sClient, sendData, strlen(sendData), 0);  
          
    }  
    closesocket(sClient);
    closesocket(slisten);  
    WSACleanup();
}

int main(int argc, char* argv[])  
{
	//服务器端代码  
    ServerSocket(); 
   return 0;  
}  

客户端:

test_socket_client.cpp

#include <stdio.h>
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>

using namespace std;

#define  IP_ADDRESS "127.0.0.1"  
 
 void ClientSocket()
 {
	WSADATA  Ws;  
    SOCKET clientSocket;  
    struct sockaddr_in serverAddr;  
    int Ret = 0;  
    int AddrLen = 0;  
    char SendBuffer[MAX_PATH]; 
	char recvData[255]; 
  
    //Init Windows Socket  
    if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )  
    {  
        cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;  
        return ;  
    }  
  
    //Create Socket  
    clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
    if ( clientSocket == INVALID_SOCKET )  
    {  
        cout<<"Create Socket Failed::"<<GetLastError()<<endl;  
        return ;  
    }  
  
    serverAddr.sin_family = AF_INET;  
    serverAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);  
    serverAddr.sin_port = htons(8888);    
  
    Ret = connect(clientSocket,(struct sockaddr*)&serverAddr, sizeof(serverAddr));  
    if ( Ret == SOCKET_ERROR )  
    {  
        cout<<"Connect Error::"<<GetLastError()<<endl;  
        return ;  
    }  
    else  
    {  
        cout<<"连接成功!"<<endl;  
    }  
    while ( true )  
    {  
        cin.getline(SendBuffer, sizeof(SendBuffer));  
        Ret = send(clientSocket, SendBuffer, (int)strlen(SendBuffer), 0);  
       if ( Ret == SOCKET_ERROR )  
        {  
            cout<<"Send Info Error::"<<GetLastError()<<endl;  
            break;  
        }
		int read =recv(clientSocket,recvData,255, 0);
		 if(read > 0)  
        {  
            recvData[read] = 0x00;  
            printf(recvData); 
			printf("\n"); 
        }  
		      
		
	 }  
  
    closesocket(clientSocket);  
    WSACleanup(); 
 }
  
 
int main(int argc, char* argv[])  
{  
	//客户端代码
     ClientSocket();
	 system("pause");
  
    return 0;  
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值