简要说明:在课设时在网上找了很久才找到一篇有所帮助的分享,本篇博客只是在原博客基础上进行了些许的修改,在此只做收藏之用!
源代码转自:https://www.cnblogs.com/imwtr/p/4072452.html
///服务器:
#include <stdlib.h>
#include <stdio.h>
#include <winsock2.h>
#include <time.h>
#include "conio.h"
#include <windows.h>
#include <process.h>
#include <math.h>
#define QLEN 5
#define WSVERS MAKEWORD(2, 0)
#define BUFLEN 2000 // 缓冲区大小
#pragma comment(lib,"ws2_32.lib") //winsock 2.2 library
SOCKET msock, ssock; /* master & slave sockets */
SOCKET sockets[100] = {NULL};
int cc;
char buf[2000]; /* buffer */
char *input;
HANDLE hThread1,hThread[100] = {NULL};
unsigned int threadID,ThreadID[100],number;
struct sockaddr_in fsin;
struct sockaddr_in Sin;
unsigned int __stdcall Chat(PVOID PM)
{
char buf1[2000];
char buf2[2000];
char buf3[2000];
char buf4[2000];
sockets[number] = ssock;
SOCKET sock = ssock;
ThreadID[number] = threadID;
unsigned int threadid = threadID;
sprintf(buf1,"【我的线程号:%d】\n",threadid);//每创建一个客户端服务器会给该客户端随机分配一个线程号
(void) send(sock,buf1, sizeof(buf1), 0);
sprintf(buf2," 线程号 <%d> 客户<IP:%s 端口:%d> 加入了! \n",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port);
printf("%s ",buf2);
for(int i=0; i<=number; i++)
{
if(sockets[i] != NULL && sockets[i] != sock)
{
(void) send(sockets[i],buf2, sizeof(buf2), 0);
printf(" 发送至线程号<%d>成功!\n",ThreadID[i]);
}
}
printf(" \n");
flag1:
cc = recv(sock, buf3, BUFLEN, 0); //cc为接收的字符数
if(cc == SOCKET_ERROR|| cc == 0)
{
sprintf( buf3," 线程号 <%d> 客户<IP:%s 端口:%d> 离开了! \n",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port);
sock = NULL;
sockets[number] = NULL;
CloseHandle(hThread[number]);
printf("%s ", buf3);
// printf("\t将自动把此数据发送给所有客户! \n");
for(int i=0; i<=number; i++)
{
if(sockets[i] != NULL && sockets[i] != sock)
{
(void) send(sockets[i], buf3, sizeof(buf3), 0);
printf(" 发送至线程号<%d>成功!\n",ThreadID[i]);
}
}
printf(" \n");
}
else if(cc > 0)
{
sprintf(buf4," 线程号 <%d> 客户<IP:%s 端口:%d>说 :%s \n ",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port,buf3);
printf("%s ",buf4);
//printf("将自动把此数据发送给所有客户! \n");
for(int i=0; i<=number; i++)
{
if(sockets[i] != NULL && sockets[i] != sock)
{
(void) send(sockets[i],buf4, sizeof(buf4), 0);
printf(" 转发至线程号<%d>成功!\n",ThreadID[i]);//将从A客户端收到的数据转发给A以外的每个客户端
}
}
printf(" \n");
goto flag1;
}
(void) closesocket(sock);
return 0;
}
DWORD WINAPI sendFunction(LPVOID lpParameter)//添加一个线程用来实现服务器端给客户端发送数据
{
char sendBuf[50];
SOCKET sock = ssock;
sockets[number] = ssock;
while(1)
{
gets(sendBuf);//scanf("%s",sendBuf);
for(int i=0; i<number; i++)
{
if(sockets[i] != NULL && sockets[i] != sock)
{
(void) send(sockets[i],sendBuf, sizeof(sendBuf), 0);
printf(" 发送成功!\n");
}
}
}
}
int main(int argc, char *argv[])
/* argc: 命令行参数个数, 例如:C:\> TCPdaytimed 8080
argc=2 argv[0]="TCPdaytimed",argv[1]="8080" */
{
int alen; /* from-address length */
WSADATA wsadata;
char *service = "5050";
WSAStartup(WSVERS, &wsadata); //加载 winsock 2.2 library
msock = socket(PF_INET, SOCK_STREAM, 0); //生成套接字。TCP协议号=6, UDP协议号=17
memset(&Sin, 0, sizeof(Sin));
Sin.sin_family = AF_INET;
Sin.sin_addr.s_addr = INADDR_ANY; //指定绑定接口的IP地址。INADDR_ANY表示绑定(监听)所有的接口。
Sin.sin_port = htons((u_short)atoi(service)); //atoi--把ascii转化为int,htons - 主机序(host)转化为网络序(network), s(short)
bind(msock, (struct sockaddr *)&Sin, sizeof(Sin)); // 绑定端口号(和IP地址)
listen(msock, 5); //队列长度为5
printf("我是服务器!!!\n");
number = -1;
while(1) //检测是否有按键
{
alen = sizeof(struct sockaddr);
ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
number ++;
hThread1=(HANDLE)_beginthreadex(NULL,0,sendFunction,NULL,0,NULL);
hThread[number] = (HANDLE)_beginthreadex(NULL, 0,Chat,NULL, 0, &threadID);
}
(void) closesocket(msock);
WSACleanup(); //卸载载 winsock 2.2 library
}
///客户端:
/* TCPClient.cpp -- 用于传递struct */
#include <stdlib.h>
#include <stdio.h>
#include <winsock2.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <process.h>
#include <math.h>
#define BUFLEN 2000 // 缓冲区大小
#define WSVERS MAKEWORD(2, 0) // 指明版本2.0
#pragma comment(lib,"ws2_32.lib") // 指明winsock 2.0 Llibrary
SOCKET sock,sockets[100] = {NULL}; /* socket descriptor */
// int cc; /* recv character count */
char *packet = NULL; /* buffer for one line of text */
char *pts,*input;
HANDLE hThread;
unsigned threadID;
unsigned int __stdcall Chat(PVOID PM )
{
char recvbuf[2000];
while(1)
{
int cc = recv(sock, recvbuf, BUFLEN, 0); //cc为接收的字符数
if(cc == SOCKET_ERROR|| cc == 0)
{
printf("Error: %d.----",GetLastError());
printf("与服务器断开连接!\n");
CloseHandle(hThread);
(void)closesocket(sock);
break;
}
else if(cc > 0)
{
printf("%s\n",recvbuf);
}
}
return 0;
}
int main(int argc, char *argv[])
{
time_t now;
(void) time(&now);
pts = ctime(&now);
char *host = "127.0.0.1"; /* server IP to connect */
char *service = "5050"; /* server port to connect */
struct sockaddr_in sin; /* an Internet endpoint address */
WSADATA wsadata;
WSAStartup(WSVERS, &wsadata); /* 启动某版本Socket的DLL */
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons((u_short)atoi(service)); //atoi:把ascii转化为int. htons:主机序(host)转化为网络序(network), s--short
sin.sin_addr.s_addr = inet_addr(host); //如果host为域名,需要先用函数gethostbyname把域名转化为IP地址
sock = socket(PF_INET, SOCK_STREAM,0);
connect(sock, (struct sockaddr *)&sin, sizeof(sin));
printf("我是客户端!!!");
hThread = (HANDLE)_beginthreadex(NULL, 0,Chat, NULL, 0, &threadID);
while(1)
{
char buf1[2000];
// scanf("%s",&buf1);
gets(buf1);
if(!strcmp(buf1 ,"exit"))
goto end;
(void) send(sock,buf1, sizeof(buf1), 0);
printf(" 发送成功!\n");
}
end: CloseHandle(hThread);
closesocket(sock);
WSACleanup(); /* 卸载某版本的DLL */
printf("按回车键继续...");
getchar();
return 0; /* exit */
}