当前位置:   article > 正文

C语言-Socket实现双人网络通信_qq 两人私聊 socket 是如何实现

qq 两人私聊 socket 是如何实现

服务端
1、负责转发双方的消息
|----1.1、接收客户端A的消息,并转发给客户端B
|----1.2、接收客户端B的消息,并转发给客户端A

客户端
1、可以发送消息给对方
2、可以接受对方的消息

关于线程
1、服务的与客户端均使用了线程,在客户端中主线程负责我方发送消息,另一个线程(函数名:ThreadReceive)用于接收对方的消息并显示在控制台(底部给出参考链接)。

工作流程图
在这里插入图片描述

详细流程
1、因为是两个客户端聊天,所以在服务端需要得到两个客户端的Socket。服务端首先等待第一个客户端连接,第一个客户端连接成功后,再等待第二个客户端连接,双方都连接后,服务端开始工作(上图绿色字体)。
2、客户端会有一个单独的线程来接收来自服务器的消息(其实接收的是对方的消息,由服务端转发)

注:服务的作用是负责转发两个客户端之间的消息,让双方都能收到对方的消息。所以服务端是等待两次Socket连接,第一次是第一个客户端,第二次是第二个客户端,在只有一个客户端连接的情况下,发消息并没有意义。

运行效果图
在这里插入图片描述
在这里插入图片描述

客户端代码(Client[32bit]V1.4.cpp)

#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <process.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
/* * * * * * * * * * * * * * * * Client * * * * * * * * *
*夏雨程_YKC
*alanlw21@qq.com
*			
*Dev-C++5.11编译报错附加:-lwsock32
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void ThreadReceive(PVOID param);
void SendReceiveException(int e);

SOCKET ClientSocket = INVALID_SOCKET;
char name[18] = "";

int main(void)
{
	system("title Client V1.4");
	system("mode con cols=60 lines=23");
	system("color 9F");
	SOCKADDR_IN ServerAddr = { 0 };
    WSADATA wsaData = { 0 };
    USHORT uPort = 47168;//服务端端口

    if (WSAStartup(MAKEWORD(2, 2), &wsaData))
    {
        printf("WSAStartup failed with error code: %d\n", WSAGetLastError());system("pause");
        return -1;
    }
    
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        printf("wVersion was not 2.2\n");system("pause");
        return -1;
    }

    ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ClientSocket == INVALID_SOCKET) {
        printf("socket failed with error code: %d\n", WSAGetLastError());system("pause");
        return -1;
    }

	//服务器地址:127.0.0.1
	char IP[20] = "127.0.0.1";
	
    printf("请输入你的昵称:");
    gets(name);
    
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(uPort);
    ServerAddr.sin_addr.S_un.S_addr = inet_addr(IP);

    printf("\n正在等待对方链接,请稍等...\n");
    if (SOCKET_ERROR == connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr))) { 
        printf("connect failed with error code: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        MessageBox(NULL,TEXT("链接服务器失败!"),TEXT("Error"),MB_OK|MB_ICONWARNING);
        return -1;
    }else{
    	printf("链接成功...\n\n\n");
	} 

    char buffer[1024] = {0};
    int iRecvLen = 0;
    int iSnedLen = 0;

	_beginthread(ThreadReceive, 0, NULL); //启动线程

    iSnedLen = send(ClientSocket, name, strlen(name), 0);
    SendReceiveException(iSnedLen);
	
    while (1)
    {
        memset(buffer, 0, sizeof(buffer));
		printf("My:"); gets(buffer);
        iSnedLen = send(ClientSocket, buffer, strlen(buffer), 0);
        SendReceiveException(iSnedLen);
    }

    closesocket(ClientSocket);
    WSACleanup();
    printf("\n通讯结束!\n");
    system("pause");
    return 0;
}

void ThreadReceive(PVOID param)
{
	char buffer[1024] = {0};
    int iRecvLen = 0;
	
    char nameOther[32] = { 0 };
    iRecvLen = recv(ClientSocket, nameOther, sizeof(nameOther), 0);
    SendReceiveException(iRecvLen);
    strcat(nameOther, "\0");
    
    while(true)
    {
    	memset(buffer, 0, sizeof(buffer));
    	iRecvLen = recv(ClientSocket, buffer, sizeof(buffer), 0);
    	SendReceiveException(iRecvLen);
    	strcat(buffer, "\0");
    	printf("\r        \r【%s】:%s", nameOther,buffer);
    	printf("\nMy:");
	}
}

void SendReceiveException(int e)
{
	if(SOCKET_ERROR == e)
	{
		printf("\n\nsend failed with error code: %d\n", WSAGetLastError());
		printf("提示:链接异常或对方可能断开了链接!\n\n");
        closesocket(ClientSocket); //关闭客户端套接字 
        WSACleanup(); //释放DLL 
        MessageBox(NULL,TEXT("链接异常或对方可能断开了链接!"),TEXT("提示"),MB_OK|MB_ICONWARNING);
        system("pause"); 
        exit(-1);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125

服务端代码(Server[32bit]V1.3.cpp)

#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <process.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")

/* * * * * * * * * * * * * * * * Server * * * * * * * * *
*夏雨程_YKC
*alanlw21@qq.com
*			
*Dev-C++5.11编译报错附加:-lwsock32
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */

typedef struct Client{
	SOCKET ServerSocket;
	SOCKET ClientSocket01;
	SOCKET ClientSocket02;
}CLS;

int init(CLS *pSer);
void CreatSocket(CLS *pcls);
void ThreadStart(CLS *pcls);
unsigned __stdcall ThreadReceive01(void* pCls);
unsigned __stdcall ThreadReceive02(void* pCls);
bool SendReceiveException(int e, CLS *p);

char Tempbuffer1[1024] = {0};
char Tempbuffer2[1024] = {0};

int main(void)
{
	system("title Server V1.3");
	system("color 1E");
	
	CLS cls;
    CLS *pcls = &cls;
	while(true)
	{
		init(pcls);
		CreatSocket(pcls);
		ThreadStart(pcls);
	} 

	while(true); 
	
    closesocket(pcls->ClientSocket01);
    closesocket(pcls->ClientSocket02);
    closesocket(pcls->ServerSocket);
    WSACleanup();
    return 0;
}

int init(CLS *pSer)
{
	SOCKADDR_IN ServerAddr = { 0 };
	pSer->ServerSocket = INVALID_SOCKET;
	USHORT uPort = 47168;
    WSADATA wsaData = { 0 };
    
    if (WSAStartup(MAKEWORD(2, 2), &wsaData)){
        printf("WSAStartup failed with error code: %d\n", WSAGetLastError());system("pause");
        return -1;
    }
    
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){
        printf("Version was not 2.2\n");
		MessageBox(NULL,TEXT("Version was not 2.2(version Error)"),TEXT("Error"),MB_OK|MB_ICONWARNING);
		system("pause");
        return -1;
    }
    
    pSer->ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    if (pSer->ServerSocket == INVALID_SOCKET) {
        printf("socket failed with error code: %d\n", WSAGetLastError());
		MessageBox(NULL,TEXT("The initialization server failed!(socket function Error)"),TEXT("Error"),MB_OK|MB_ICONWARNING);
		system("pause");
        return -1;
    }

    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(uPort);//服务器监听端口
    ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    if (SOCKET_ERROR == bind(pSer->ServerSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr))){
        printf("bind failed with error code: %d\n", WSAGetLastError());
        closesocket(pSer->ServerSocket);system("pause");
        return -1;
    }
    
    if (SOCKET_ERROR == listen(pSer->ServerSocket, 3))
    {
        printf("listen failed with error code: %d\n", WSAGetLastError());
        closesocket(pSer->ServerSocket);
        WSACleanup();system("pause");
        return -1;
    }
} 

void CreatSocket(CLS *pcls)
{
    pcls->ClientSocket01 = INVALID_SOCKET;
    pcls->ClientSocket02 = INVALID_SOCKET;
    SOCKADDR_IN ClientAddr01 = { 0 };
    SOCKADDR_IN ClientAddr02 = { 0 };

    printf("\nwaiting connect.....\n\n");
    
	int ClientAddrLength01 = sizeof(ClientAddr01);
	int ClientAddrLength02 = sizeof(ClientAddr02);
	
    pcls->ClientSocket01 = accept(pcls->ServerSocket, (SOCKADDR*)&ClientAddr01, &ClientAddrLength01);//等待客户端1链接... 
    printf("Client01 link to success, wait for Client02 link...\n");
    pcls->ClientSocket02 = accept(pcls->ServerSocket, (SOCKADDR*)&ClientAddr02, &ClientAddrLength02);//等待客户端2链接... 
    printf("Client02 link to success,Start connect.\n\n");
    if (pcls->ClientSocket01 == INVALID_SOCKET || pcls->ClientSocket02 == INVALID_SOCKET) {
        printf("accept failed with error code: %d\n", WSAGetLastError());
        closesocket(pcls->ServerSocket);
        WSACleanup();//释放dll资源 
        MessageBox(NULL,TEXT("接收两个客户端出错,请重启服务器!"),TEXT("Error"),MB_OK|MB_ICONWARNING);
        exit(-1);
    }
}

void ThreadStart(CLS *pcls)
{
	HANDLE hThread01;
	HANDLE hThread02;
    unsigned threadID01;unsigned threadID02;
    
	printf("双方连接成功,开始聊天...\n\n"); 
	
    hThread01 = (HANDLE)_beginthreadex( NULL, 0, &ThreadReceive01, pcls, 0, &threadID01 );
    
    hThread02 = (HANDLE)_beginthreadex( NULL, 0, &ThreadReceive02, pcls, 0, &threadID02 );
    WaitForSingleObject(hThread01, INFINITE);
    WaitForSingleObject(hThread02, INFINITE);
	CloseHandle(hThread01);
	CloseHandle(hThread02);
}

//线程1-客户端01 
unsigned __stdcall ThreadReceive01(void* pCls)
{
	int isError = 0;
	bool flag = true;
	CLS *p = (CLS*)pCls;
	
	char name[20] = { 0 };
    isError = recv(p->ClientSocket01, name, sizeof(name), 0);
	if(SendReceiveException(isError, p))flag=false;
	
    isError = send(p->ClientSocket02, name, strlen(name), 0);
    if(SendReceiveException(isError, p))flag=false;
    printf("用户:%s---上线\n\n",name);

	while(flag)
	{
		memset(Tempbuffer1, 0, sizeof(Tempbuffer1));
		
    	isError = recv(p->ClientSocket01, Tempbuffer1, sizeof(Tempbuffer1), 0);
    	if(SendReceiveException(isError, p))flag=false;
    	strcat(Tempbuffer1, "\0");
    	printf("【%s】:%s\n",name,Tempbuffer1);
        isError = send(p->ClientSocket02, Tempbuffer1, strlen(Tempbuffer1), 0);
        if(SendReceiveException(isError, p))flag=false;
	}
}

//线程2-客户端02
unsigned __stdcall ThreadReceive02(void* pCls)
{
	int isError = 0;
	bool flag = true; //判断错误
	CLS *p = (CLS*)pCls;
	
	// 接收客户端02的用户名 
	char name[20] = { 0 };
    isError = recv(p->ClientSocket02, name, sizeof(name), 0);
	if(SendReceiveException(isError, p))flag=false;
	
    isError = send(p->ClientSocket01, name, strlen(name), 0);
    if(SendReceiveException(isError, p))flag=false;
    printf("用户:%s---上线\n\n",name);
    
	while(flag)
	{
		memset(Tempbuffer2, 0, sizeof(Tempbuffer2));
		
    	isError = recv(p->ClientSocket02, Tempbuffer2, sizeof(Tempbuffer2), 0);
    	if(SendReceiveException(isError, p))flag=false;
    	strcat(Tempbuffer2, "\0");
    	printf("【%s】:%s\n",name,Tempbuffer2);
    	
        isError = send(p->ClientSocket01, Tempbuffer2, strlen(Tempbuffer2), 0);
        if(SendReceiveException(isError, p))flag=false;
	}
}

bool SendReceiveException(int e, CLS *p)
{
	if(SOCKET_ERROR == e)
	{
		printf("send failed with error code: %d\n", WSAGetLastError());
        closesocket(p->ServerSocket);
        closesocket(p->ClientSocket01);
        closesocket(p->ClientSocket02);
        
        printf("\nException function:User disconnected or error,Close all Sockets!But no DLL file is freed.\n");

       	return true;
	}
	return false;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216

关于编译时可能遇到的问题

此程序是在Dev-C++5.11下编译的,如果遇到报错:在这里插入图片描述
则添加“-lwsock32”:
在这里插入图片描述
此错误参考

此代码中线程,参考文档

—End—

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/144088
推荐阅读
相关标签
  

闽ICP备14008679号