小练习:用socket实现Linux和Windows之间的通信

Posted wzjhoutai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小练习:用socket实现Linux和Windows之间的通信相关的知识,希望对你有一定的参考价值。

在日常生活中,绝大部分人使用的机器通常是windows系统,可是对于研发人员,开发、编译等工作往往是建立在linux机器上。其实。在服务器方面,Linux、UNIX和WindowsServer占领了市场的大部分份额;在超级计算机方面,Linux代替Unix成为了第一大操作系统。

通信是计算机和操作系统的一大任务,通过ftp、ping、ssh等方式。人们能够非常方便与服务器连接。一个庞大的网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

windows系统使用的是windows socket,而linux使用的posix socket。今天结合了网上一些经典例程,写了一个简单的socket代码,实现Ubuntu(虚拟机中)和Windows的通信。

Windows平台下客户端的实现代码:

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

#pragma comment(lib, "ws2_32.lib")
#define Port 5000
#define IP_ADDRESS "172.30.70.95"

int main(int argc, char* argv[]) // argc是命令行总的參数个数
{

        WSADATA s; // 用来储存调用AfxSocketInit全局函数返回的Windows Sockets初始化信息
        SOCKET ClientSocket;
        struct sockaddr_in ClientAddr; // 一个sockaddr_in型的结构体对象
        int ret = 0;
        char SendBuffer[MAX_PATH];   // Windows的MAX_PATH默认是260

        // 初始化Windows Socket
        // WSAStartup函数对Winsock服务的初始化
        if (WSAStartup(MAKEWORD(2, 2), &s) != 0) // 通过连接两个给定的无符号參数,首个參数为低字节
        {
            printf("Init Windows Socket Failed! Error: %d\n", GetLastError());
            getchar();
            return -1;
        }

        while (1)
        {
        // 创建一个套接口
        // 假设这样一个套接口用connect()与一个指定端口连接
        // 则可用send()和recv()与该端口进行数据报的发送与接收
        // 当会话结束后,调用closesocket()
        ClientSocket = socket(AF_INET, // 仅仅支持ARPA Internet地址格式
            SOCK_STREAM, // 新套接口的类型描写叙述
            IPPROTO_TCP); // 套接口所用的协议
        if (ClientSocket == INVALID_SOCKET)
        {
            printf("Create Socket Failed! Error: %d\n", GetLastError());
            getchar();
            return -1;
        }

        ClientAddr.sin_family = AF_INET;
        ClientAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS); // 定义IP地址
        ClientAddr.sin_port = htons(Port); // 将主机的无符号短整形数转换成网络字节顺序
        memset(ClientAddr.sin_zero, 0X00, 8); // 函数通常为新申请的内存做初始化工作

        // 连接Socket
        ret = connect(ClientSocket,
            (struct sockaddr*)&ClientAddr,
            sizeof(ClientAddr));
        if (ret == SOCKET_ERROR)
        {
            printf("Socket Connect Failed! Error:%d\n", GetLastError());
            getchar();
            return -1;
        }
        else
        {
            printf("Socket Connect Succeed!");
        }

        printf("Input Data: ");
        while (1)
        {
            scanf("%s", &SendBuffer);

            // 发送数据至服务器
            ret = send(ClientSocket,
                SendBuffer,
                (int)strlen(SendBuffer), // 返回发送缓冲区数据长度
                0);

            if (ret == SOCKET_ERROR)
            {
                printf("Send Information Failed! Error:%d\n", GetLastError());
                getchar();
                break;
            }

            break;
        }

        // 关闭socket
        closesocket(ClientSocket);
        if (SendBuffer[0] == ‘q‘) // 设定输入第一个字符为q时退出
        {
            printf("Quit!\n");
            break;
        }

    }   
        WSACleanup();
                    getchar();
        return 0;
}

我的linux(Ubuntu)端网络信息:

技术分享

linux(Ubuntu)平台下的服务器代码:

#include <unistd.h>
#include <stdio.h>
#include <i386-linux-gnu/sys/socket.h>
#include <netinet/in.h>
#include <i386-linux-gnu/sys/types.h>
#include <stdlib.h>
#include <string.h>

#define SERVER_PORT 5000
#define LENGTH_OF_LISTEN_QUEUE 20
#define BUFFER_SIZE 10

int main() // (int argc, char* argv[])
{
    struct sockaddr_in server_addr;
    int server_socket;
    int opt = 1;

    bzero(&server_addr, sizeof(server_addr)); // 置字节字符串前n个字节为0,包含‘\0‘
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htons(INADDR_ANY); // 转小端,INADDR_ANY就是指定地址为0.0.0.0的地址
    server_addr.sin_port = htons(SERVER_PORT);  

    // 创建一个Socket
    server_socket = socket(PF_INET, SOCK_STREAM, 0);

    if (server_socket < 0)
    {
        printf("Create Socket Failed!\n");
        exit(1);
    }


    // bind a socket
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    if(bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))
    {
        printf("Server Bind Port: %d Failed!\n", SERVER_PORT);
        exit(1);
    }

    // 监听Socket
    if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))
    {
        printf("Server Listen Failed!\n");
        exit(1);
    }      

    while(1)
    {

        struct sockaddr_in client_addr;
        int client_socket;
        socklen_t length;
        char Buffer[BUFFER_SIZE];

        // 连接客户端Socket
        length = sizeof(client_addr);
        client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);
        if (client_socket < 0)
        {
            printf("Server Accept Failed!\n");
            break;
        }

        // 从客户端接收数据
        while(1)
        {
            bzero(Buffer, BUFFER_SIZE);
            length = recv(client_socket, Buffer, BUFFER_SIZE, 0);

            if (length < 0)
            {
                printf("Server Recieve Data Failed!\n");
                break;
            }           

            if (‘q‘ == Buffer[0])
            {
                printf("Quit!\n");
                break;
            }

            printf("%s\n", Buffer);
            break;

        }

        close(client_socket);
    }

    close(server_socket);
    return 0;
}

在打开客户端时。服务器端要确保已处于监听状态,否则连接失败:

技术分享

打开服务器端程序例如以下:

技术分享

传输数据成功:

技术分享

这个小实验仅仅花了非常少的时间调试,且仅仅能单向发送数据。功能单一。纯粹仅仅是一个小练习。socket编程的调试中,主要关注程序出错时返回的错误值,从中往往能非常快找出代码的漏洞。

參考链接:http://blog.csdn.net/feixiaoxing/article/details/8567162

以上是关于小练习:用socket实现Linux和Windows之间的通信的主要内容,如果未能解决你的问题,请参考以下文章

socket小练习:通过server端,执行cmd命令

Linux Linux程序练习十二(select实现QQ群聊)

新手MFC学习之Socket练习

Linux小练习打包并使用动静态库

Linux小练习打包并使用动静态库

Linux小练习进度条程序