使用socket 情况下的windows系统与ubuntu16.04系统通信

本文详细介绍了如何在Windows与Ubuntu16.04系统之间使用socket进行通信,包括更改网络IP地址,分别在两个系统下编写并编译程序,以及通信测试和注意事项。在通信实验中,需确保双方IP地址在同一子网内,且顺序正确,先启动服务器端程序,再启动客户端程序。

1.1 更改网络IP地址

1.1 windows系统更改IP地址

右下角网络→右击打开网络和Internet设置→更改适配器选项→右击VMware Network Adapter VMnet8→属性→双击Internet网络协议4→更改如下
在这里插入图片描述

1.2 ubuntu系统更改IP地址

右上角系统设置→network→右下角options→选择IPv4 settings→下拉选择Manual→Add→填写地址Address与Netmask分别为192.168.0.1 与255.255.255.0,如下
在这里插入图片描述
点击保存,在Network界面选择重启,即可生效,如下
在这里插入图片描述
备注,两系统的IP地址只需保证前三段一致,最后一位不同即可,无需与上述设置必须一致,比如
windows:192.168.2.1 ubuntu:192.168.2.2

2. 程序编写

2.1 windows下程序代码

client端

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

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

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;
}

2.2 ubuntu下程序代码

server端

#include <unistd.h>
#include <stdio.h>
#include <x86_64-linux-gnu/sys/socket.h>
#include <netinet/in.h>
#include <x86_64-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;
}

3. 编译

windows 下使用vc++6.0编译。
ubuntu下使用gcc编译

4. 通信

4.1 通信前的测试

(可跳过,但建议试一试)
从windows端向ubuntu端ping:
打开windows系统 cmd,输入:ping 192.168.0.1
在这里插入图片描述
从ubuntu端向windows端ping:
打开ubuntu系统终端 ,输入:ping 192.168.0.2
在这里插入图片描述
互相ping成功,说明可以进行通信。若在通信实验中失败,使用ping检查是一个方向。

4.2 通信实验

注意顺序:
打开ubuntu终端,运行第三步编译的可执行程序;再打开vc++6.0,运行client客户端程序。
在客户端会出现如下界面,说明通信成功:
在这里插入图片描述
在windows端输字符串,在ubuntu端即可接收,效果如下:
在这里插入图片描述在这里插入图片描述

4.3 注意

若在建立通信过程中出现如下错误:
在这里插入图片描述
解决方案可尝试如下:

  1. 程序执行顺序:先server端(本例中为ubuntu端),后client端(本例中为windows端)
  2. 在网络适配器设置中,关闭windows互联网网络连接,或者拔掉网线,再运行程序。
  3. 查看虚拟机的网络设置,可尝试将网络连接该改为VMnet8(NAT模式)在这里插入图片描述
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值