| 网站首页 | 业界新闻 | 群组 | 交易 | 人才 | 下载频道 | 博客 | 代码贴 | 编程论坛
共有 396 人关注过本帖
标题:【菜鸡求助,谢谢大佬~】socket通信+线程(代码已贴,研究两天无果 T_T)
只看楼主 加入收藏
是心愿
Rank: 1
等 级:新手上路
帖 子:75
专家分:0
注 册:2016-6-22
结帖率:71.43%
  已结贴   问题点数:20  回复次数:15   
【菜鸡求助,谢谢大佬~】socket通信+线程(代码已贴,研究两天无果 T_T)
client发data的方式不同导致结果不同。发数据的两种方式用感叹号标出了
想用循环达到方式2的效果,但是方式1的结果运行的不对。到底哪里错了呢?求指教~~~



client端:
程序代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include "winsock2.h"
#pragma comment(lib,"ws2_32.lib")//引用库文件
using namespace std;

SOCKET sockClient[2];    //新!
char recvBuf[2][20];//新!
HANDLE hHandle;//
HANDLE existHandle[2];
int thread[2];

DWORD WINAPI Fun(LPVOID lp)
{
    int serverId = *(int*)(lp);
    DWORD hRes = 0;

    printf("enter Fun,serverId=%d \n", serverId);

    //用线程接收数据2

    if (recv(sockClient[serverId], recvBuf[serverId], sizeof(recvBuf), 0) <= 0) {
        printf("接受失败");

    }
    else {
        //printf("recvBuf[%d]=%s\n", serverId, recvBuf[serverId]);
        
//closesocket(sockClient);

        
//发送数据3
        char result1[] = "sat";
        char result2[] = "unsat";
        char buffs1[100] = "satStop";
        char buffs2[100] = "unsatGoon";
        if (strcmp(recvBuf[serverId], result1) == 0) {//sat

            printf("recvBuf[%d]=%s\n", serverId, recvBuf[serverId]);
            for (int i = 0;i < 2;i++) {
                if (i != serverId) {        //server1 sat 则给server2发stop
                    printf("here is sat,send to server%d to stop:%s\n", i, buffs1);
                    send(sockClient[i], buffs1, sizeof(buffs1), 0);                    //这里是i不是serverId了
                }
            }



            SetEvent(existHandle[serverId]);
        }
        else if (strcmp(recvBuf[serverId], result2) == 0) {//unsat

            printf("recvBuf[%d]=%s\n", serverId, recvBuf[serverId]);
            printf("server%d unsat\n", serverId);
            //printf("here is unsat send to server%d :%s\n", serverId, buffs2);
            
//send(sockClient[serverId], buffs2, sizeof(buffs2), 0);
            SetEvent(existHandle[serverId]);
        }
        else {
            printf("绝望了\n");
        }


        //closesocket(sockClient[serverId]);



        return 0;
    }


    //closesocket(sockClient);
   
//return 0;
}



int main()
{
    printf("This is client\n");
    //加载套接字
    WSADATA wsaData;
    char buff[1024];
    memset(buff, 0, sizeof(buff));

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        printf("初始化Winsock失败");
        return 0;
    }


    SOCKADDR_IN addrSrv[2];
    //端口号 IP
    addrSrv[0].sin_family = AF_INET;
    addrSrv[0].sin_port = htons(8888);
    addrSrv[0].sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    //端口号 IP
    addrSrv[1].sin_family = AF_INET;
    addrSrv[1].sin_port = htons(2222);
    addrSrv[1].sin_addr.S_un.S_addr = inet_addr("127.0.0.1");


    //SOCKET sockClient[2];
    for (int i = 0;i < 2;i++) {

        //创建套接字
        sockClient[i] = socket(AF_INET, SOCK_STREAM, 0);
        if (SOCKET_ERROR == sockClient[0]) {
            printf("Socket() error:%d", WSAGetLastError());
            return 0;
        }

        //向服务器发出连接请求
        if (connect(sockClient[i], (struct  sockaddr*)&addrSrv[i], sizeof(addrSrv[i])) == INVALID_SOCKET) {
            printf("server1连接失败:%d", WSAGetLastError());
            return 0;
        }
    }

    /**
    //向server0,server1  发送数据1(方式1)!!!!
    char databuf[2][100];
    string str0 = "000000";
    string str1 = "111111";
    int length0 = str0.copy(databuf[0], 6);
    databuf[0][length0] = '\0';
    int length1 = str1.copy(databuf[1], 6);
    databuf[1][length1] = '\0';


    for (int i = 0;i < 2;i++) {

        send(sockClient[i], databuf[i], sizeof(databuf), 0);
        printf("send to server%d:%s\n", i, databuf[i]);
    }
   
*/

   

    /**
    //向server0,server1  发送数据1  (方式2)!!!!
    char databuf0[7] = "000000";
    char databuf1[7] = "111111";
    send(sockClient[0], databuf0, sizeof(databuf0), 0);
    send(sockClient[1], databuf1, sizeof(databuf1), 0);
   
*/

    printf("用线程接收数据\n ");
    //创建事件  
    for (int i = 0;i < 2;i++) {
        existHandle[i] = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    }


    HANDLE hThread[8];
    //创建两线程
    int ID[2];
    for (int i = 0;i < 2;i++) {
        ID[i] = i;
        hThread[i] = CreateThread(NULL, 0, Fun, &ID[i], 0, NULL);

    }


    //等待全部线程运行结束
    int cn = 0;
    while (true)
    {
        printf("没wait到呢\n ");
        DWORD hr = WaitForMultipleObjects((DWORD)2, existHandle, false, INFINITE);
        if (hr == WAIT_FAILED) {
            break;
            printf("hr == WAIT_FAILED\n ");
        }
        cn++;
        printf("1\n ");
        if (cn >= 2)    //两个线程都执行完毕
        {
            printf("主线程要结束了\n ");
            break;
        }
    }
    //关闭套接字
   
//closesocket(sockClient[0]);
   
//closesocket(sockClient[1]);
    WSACleanup();//释放初始化Ws2_32.dll所分配的资源。
    system("pause");//让屏幕暂留
    return 0;
}



server1
程序代码:
#include <iostream>
#include <stdlib.h>
#include "project.h"
#include <stdio.h>
#include "winsock2.h"
#include<cstdlib>
#pragma comment(lib,"ws2_32.lib")//引用库文件
using namespace std;


char recvBuf1[49];
short buff[49];
SOCKET sockConn;
HANDLE hEvent;


DWORD WINAPI Fun(LPVOID lpParamter)
{
    char buff2[100];
    char result[] = "satStop";
    memset(buff2, 0, sizeof(buff2));
    if (recv(sockConn, buff2, sizeof(buff2), 0) < 0) {
        printf("Receive fail\n");
    }
    else {
        printf("Receive form client success:%s\n", buff2);
        if (strcmp(buff2, result) == 0) {
            SetEvent(hEvent);
        }

        return 0;
    }

}



int main()
{
    printf("server0 ready\n");
    WSADATA wsaData;
    int port = 8888;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        printf("初始化失败");
        return 0;
    }

    //创建用于监听的套接字,即服务端的套接字
    SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
    SOCKADDR_IN addrSrv;
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(port);
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    //bind
    int retVal = bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));
    if (retVal == SOCKET_ERROR) {
        printf("连接失败:%d\n", WSAGetLastError());
        return 0;
    }
    //listen
    if (listen(sockSrv, 10) == SOCKET_ERROR) {
        printf("监听失败:%d", WSAGetLastError());
        return 0;
    }

    SOCKADDR_IN addrClient;
    int len = sizeof(SOCKADDR);

    while (1)
    {
        //等待客户请求到来
        sockConn = accept(sockSrv, (SOCKADDR *)&addrClient, &len);
        if (sockConn == SOCKET_ERROR) {
            printf("等待请求失败:%d", WSAGetLastError());
            break;
        }

        printf("客户端的IP是:[%s]\n", inet_ntoa(addrClient.sin_addr));



        //接收confirm
        recv(sockConn, recvBuf1, sizeof(recvBuf1), 0);
        cout << recvBuf1;
        printf("char buff end\n");

        //将buf转为short类型
        for (int j = 0;j < 48;j++) {
            buff[j] = recvBuf1[j] - '0';
            //cout << "Shh " << buffs[i][j];
            printf("buff][%d] = %d", j, buff[j]);
            printf("\n short buf end\n");
        }

        //将数据赋值给confirm
        bool isTrue = ConfirmedVar(buff);
        if (isTrue == 0) {
            printf("has confirmed");
            //printf(ConfirmedVariableAllUnitsAssignment[][]);
        }


        //发送数据2

        char sendbuf1[] = "unsat";
        int Send = send(sockConn, sendbuf1, sizeof(sendbuf1), 0);
        if (Send == SOCKET_ERROR) {
            printf("发送失败");
            break;
        }
        else {
            printf("unsat发送成功\n");
        }


        hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

        int id[2];
        HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Fun, &id[0], 0, NULL);

        int cn2 = 0;
        while (true)
        {
            printf("没wait到呢\n ");
            DWORD hr = WaitForSingleObject(hEvent, INFINITE);
            if (hr == WAIT_FAILED) {
                break;
                printf("hr == WAIT_FAILED\n ");
            }
            cn2++;
            printf("cn2=%d\n ", cn2);
            if (cn2 >= 1)    //两个线程都执行完毕
            {
                printf("子线程setEvent了,主线程要结束了\n ");
                break;
            }
        }

        closesocket(sockConn);

    }//while

    closesocket(sockSrv);
    WSACleanup();
    system("pause");
    return 0;
}



server2
程序代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include "winsock2.h"
#include<cstdlib>
#pragma comment(lib,"ws2_32.lib")//引用库文件
using namespace std;



char recvBuf[100];
SOCKET sockConn;
HANDLE hEvent;



DWORD WINAPI Fun(LPVOID lpParamter)
{
    char buff2[100];
    char result[] = "satStop";
    memset(buff2, 0, sizeof(buff2));
    if (recv(sockConn, buff2, sizeof(buff2), 0) < 0) {
        printf("Receive fail\n");
    }
    else {
        printf("Receive form client success:%s\n", buff2);
        if (strcmp(buff2, result) == 0) {
            SetEvent(hEvent);
        }

        return 0;
    }
    return 0;
}



int main()
{
    printf("This is server 1\n");
    WSADATA wsaData;
    int port = 2222;//端口号
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        printf("初始化失败");
        return 0;
    }

    //创建用于监听的套接字,即服务端的套接字
    SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);

    SOCKADDR_IN addrSrv;
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(port); //1024以上的端口号

    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    int retVal = bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));
    if (retVal == SOCKET_ERROR) {
        printf("连接失败:%d\n", WSAGetLastError());
        return 0;
    }

    if (listen(sockSrv, 10) == SOCKET_ERROR) {
        printf("监听失败:%d", WSAGetLastError());
        return 0;
    }

    SOCKADDR_IN addrClient;
    int len = sizeof(SOCKADDR);

    while (1)
    {
        //等待客户请求到来
        sockConn = accept(sockSrv, (SOCKADDR *)&addrClient, &len);
        if (sockConn == SOCKET_ERROR) {
            printf("等待请求失败:%d", WSAGetLastError());
            break;
        }

        
        //接收数据1
        recv(sockConn, recvBuf, sizeof(recvBuf), 0);
        printf("Receive form client:%s\n", recvBuf);
        

        //发送数据2
        char sendbuf1[] = "unsat";
        int Send = send(sockConn, sendbuf1, sizeof(sendbuf1), 0);
        if (Send == SOCKET_ERROR) {
            printf("发送失败");
            break;
        }



        hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

        int id[2];
        HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Fun, &id[0], 0, NULL);

        int cn2 = 0;
        while (true)
        {
            printf("没wait到呢\n ");
            DWORD hr = WaitForSingleObject(hEvent, INFINITE);
            if (hr == WAIT_FAILED) {
                break;
                printf("hr == WAIT_FAILED\n ");
            }
            cn2++;
            printf("cn2=%d\n ", cn2);
            if (cn2 >= 1)    //两个线程都执行完毕
            {
                printf("子线程setEvent了,主线程要结束了\n ");
                break;
            }
        }

    }

    closesocket(sockConn);
    closesocket(sockSrv);
    WSACleanup();
    system("pause");
    return 0;
}
2018-08-07 17:25
是心愿
Rank: 1
等 级:新手上路
帖 子:75
专家分:0
注 册:2016-6-22
  得分:0 
就lient发数据用的是方式1时,第一个server会莫名其妙的收到111111,但是111111我只给第二个server发了呀。不用循环就没有这种问题,但我真的好想用循环...
2018-08-07 17:32
no1xijin
Rank: 6Rank: 6
来 自:江西
等 级:侠之大者
威 望:1
帖 子:82
专家分:463
注 册:2015-7-8
  得分:5 
服务器1我编译不了: fatal error C1083: Cannot open include file: 'project.h': No such file or directory
7 天前 09:57
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:151
帖 子:6007
专家分:26257
注 册:2014-5-20
  得分:5 
(方式1)!!!!
send(sockClient[i], databuf[i], sizeof(databuf), 0);
(方式2)!!!!
send(sockClient[0], databuf0, sizeof(databuf0), 0);
其中的sizeof(databuf)与sizeof(databuf0)相同吗?
7 天前 10:27
是心愿
Rank: 1
等 级:新手上路
帖 子:75
专家分:0
注 册:2016-6-22
  得分:0 
回复 3楼 no1xijin
您好 那个server中的project.h直接删掉就可以,我没有用到那个。这个程序是按照我之间的程序化简的,忘记删啦
7 天前 15:26
是心愿
Rank: 1
等 级:新手上路
帖 子:75
专家分:0
注 册:2016-6-22
  得分:0 
回复 4楼 吹水佬
您好 好像不是这个问题,因为我现在两个发送方式都不行了。server端的线程中的recv都接受失败了
7 天前 15:29
烟雨晨曦
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:6
帖 子:140
专家分:555
注 册:2017-3-5
  得分:5 
发送长度的问题
send(sockClient[i], databuf[i], sizeof(databuf), 0);
sizeof(databuf)=200
databuf[i]只是一个地址你第一次发送的时候相当于发送了databuf整个内容
7 天前 15:43
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:151
帖 子:6007
专家分:26257
注 册:2014-5-20
  得分:0 
以下是引用是心愿在2018-8-8 15:29:44的发言:

您好 好像不是这个问题,因为我现在两个发送方式都不行了。server端的线程中的recv都接受失败了

还没运行起来就谈不上什么结果对不对了
调试运行起来,或者先暂时不用多线程看看。
7 天前 15:49
是心愿
Rank: 1
等 级:新手上路
帖 子:75
专家分:0
注 册:2016-6-22
  得分:0 
回复 8楼 吹水佬
您好,这个可以运行 只是其他send recv都成功了,只有server端线程中的recv失败。。去掉线程的话一个client给一个server发都没有问题,变成两个server就recv不到了
7 天前 16:13
是心愿
Rank: 1
等 级:新手上路
帖 子:75
专家分:0
注 册:2016-6-22
  得分:0 
回复 4楼 吹水佬
您好  databuf是个二维数组,一次发一行        databuf0是个一维的字符串
7 天前 16:19







关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.033951 second(s), 8 queries.
Copyright©2004-2018, BCCN.NET, All Rights Reserved