C语言实现双人聊天

这是一个使用C语言编写的TCP/IP服务器和客户端程序,实现了简单的双人聊天功能。服务器端可以接受两个客户端的连接,并在两个客户端间转发消息。客户端输入用户名和IP地址后,能够与服务器建立连接并进行聊天。程序中包含了异常处理,如错误的连接、发送和接收。
摘要由CSDN通过智能技术生成

服务端.c:

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

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("mode con cols=60 lines=30");
	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());
		printf("WSA启动失败!错误代码:%d\n\n",WSAGetLastError());
		system("pause");
		return -1;
	}
	if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
	{
		printf("Version was not 2.2\n");
		printf("版本非2.2\n\n");
		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());
		printf("连接失败!错误代码:%d\n\n",WSAGetLastError());
		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());
		printf("绑定失败!错误代码:%d\n\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());
		printf("侦听失败!错误代码:%d\n\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("Waiting connect...\n");
	printf("等待连接...\n\n");
	int ClientAddrLength01=sizeof(ClientAddr01);
	int ClientAddrLength02=sizeof(ClientAddr02);
	pcls->ClientSocket01=accept(pcls->ServerSocket,(SOCKADDR*)&ClientAddr01,&ClientAddrLength01);
	printf("Client01 link to success,wait for Client02 link...\n");
	printf("用户01连接成功,等待用户02连接...\n\n");
	pcls->ClientSocket02=accept(pcls->ServerSocket,(SOCKADDR*)&ClientAddr02,&ClientAddrLength02);
	printf("Client02 link to success.\n");
	printf("用户02连接成功.\n\n");
	if (pcls->ClientSocket01==INVALID_SOCKET||pcls->ClientSocket02==INVALID_SOCKET)
	{
		printf("Accept failed with error code: %d\n",WSAGetLastError());
		printf("信号接收失败!错误代码:%d\n\n",WSAGetLastError());
		closesocket(pcls->ServerSocket);
		WSACleanup();
		exit(-1);
	}
}

void ThreadStart(CLS *pcls)
{
	HANDLE hThread01;
	HANDLE hThread02;
	unsigned threadID01;
	unsigned threadID02;
	printf("Start connect,begin chat...\n");
	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);
}

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("User:%s---online\n",name);
	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\n",name,Tempbuffer1);
		isError=send(p->ClientSocket02,Tempbuffer1,strlen(Tempbuffer1),0);
		if(SendReceiveException(isError,p))flag=false;
	}
}

unsigned __stdcall ThreadReceive02(void* pCls)
{
	int isError=0;
	bool flag=true;
	CLS *p=(CLS*)pCls;
	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("User:%s---online\n",name);
	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\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());
		printf("发送失败!错误代码:%d\n\n",WSAGetLastError());
		closesocket(p->ServerSocket);
		closesocket(p->ClientSocket01);
		closesocket(p->ClientSocket02);
		printf("\nException function:\nUser disconnected or error,Close all Sockets!But no DLL file is freed.\n");
		printf("\n异常:\n用户断开连接或出错,关闭所有连接!但是没有DLL文件被释放.\n\n");
		return true;
	}
	return false;
}

​

客户端.c:

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

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");
	SOCKADDR_IN ServerAddr={0};
	WSADATA wsaData={0};
	USHORT uPort=47168;
	if(WSAStartup(MAKEWORD(2,2),&wsaData))
	{
		printf("WSA启动失败!错误代码:%d\n\n",WSAGetLastError());
		system("pause");
		return -1;
	}
	if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
	{
		printf("版本非2.2\n\n");
		system("pause");
		return -1;
	}
	ClientSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(ClientSocket==INVALID_SOCKET)
	{
		printf("连接失败!错误代码:%d\n\n",WSAGetLastError());
		system("pause");
		return -1;
	}
	char *IP;
    printf("请输入IP地址:");
	gets(IP);
	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("\n连接失败!错误代码:%d\n\n",WSAGetLastError());
		closesocket(ClientSocket);
		WSACleanup();
		return -1;
	}
	else
		printf("连接成功...\n\n\n");
	system("pause");
	system("cls");
	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("[%s]:",name);
		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("\n[%s]:",name);
	}
}

void SendReceiveException(int e)
{
	if(SOCKET_ERROR==e)
	{
		printf("信号接收失败!错误代码:%d\n",WSAGetLastError());
		printf("连接异常或对方可能断开了链接!\n\n");
		closesocket(ClientSocket);
		WSACleanup();
		system("pause");
		exit(-1);
	}
}
​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值