1.实验要求:服务器和多客户端进行通信,服务端显示客户IP地址:学号、姓名、性别、考试成绩。收到学号为end结束通信。
服务端程序
#include<iostream>
#include"winsock2.h"
#include"WS2tcpip.h" //本程序用到地址转换函数inet_pton(),所以要包含该头文件
#include"process.h"
#include<windows.h>
#define PORT 65432 //定义要访问的服务器端口常量
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void tcpsend(void* par);
struct Student {
char sStID[10];
char sName[20];
char sex[10];
int examination;
};
int main()
{
SOCKET sock_server, newsock;
struct sockaddr_in addr, client_addr;
unsigned hThread;
/*初始化winsock DLL*/
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
cout << "加载winsock.dll失败!\n";
return 0;
}
/*创建套接字*/
// if ((sock_server=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
{
cout << "创建套接字失败!"<<WSAGetLastError()<<endl;
WSACleanup();
return 0;
}
/*绑定IP端口*/
int addr_len = sizeof(struct sockaddr_in);
memset((void*)&addr, 0, addr_len);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
/*给监听套接字绑定地址*/
// if (bind(sock_server,(LPSOCKADDR)&addr,sizeof(addr))!=0)
if (bind(sock_server, (struct sockaddr*)&addr, sizeof(addr)) != 0)
{
cout << "绑定地址失败!"<<WSAGetLastError()<<endl;
closesocket(sock_server);
WSACleanup();
return 0;
}
/*开始监听*/
if (listen(sock_server,0)!=0)
{
cout << "listen函数调用失败!"<<WSAGetLastError()<<endl;
closesocket(sock_server);
WSACleanup();
return 0;
}
else
{
cout << "listenning......\n";
}
/*接收并处理客户连接*/
char client_ip[20];
in_addr a;
while(true)
{
// newsock = accept(sock_server, (LPSOCKADDR)&client_addr, &addr_len);
newsock = accept(sock_server, (struct sockaddr*)&client_addr, &addr_len);
if (newsock!=INVALID_SOCKET)
{
a = client_addr.sin_addr;
cout << "connet from" << " " << inet_ntop(AF_INET, &a, client_ip, 20) <<"\n";
/*创建线程*/
hThread=_beginthread(tcpsend, 0, (LPVOID)newsock);
}
else
{
break;
}
}
closesocket(newsock);
closesocket(sock_server);
WSACleanup();
return 0;
}
void tcpsend(void* par)
{
struct Student stud;
int size;
SOCKET sock = (SOCKET)par;
while (true)
{
if ((size = recv(sock, (char*)&stud, sizeof(struct Student), 0))<0)
{
cout << "接收信息失败,错误码:" << WSAGetLastError() << endl;
// break;
}
else if (size==0)
{
cout << "数据传输完成" << endl;
break;
}
else //输出收到的数据
{
//将数据中的整型数据字段的值由网络字节顺序转换为主机字节顺序
stud.examination = htonl(stud.examination);
cout << "收到的学生信息为:\n";
cout << stud.sStID << " " << stud.sName << " " << stud.sex << " " << stud.examination << endl;
}
Sleep(1000);
}
}
客户端程序:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <iostream>
#define PORT 65432
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
struct Student {
char sStID[10];
char sName[20];
char sex[10];
int examination;
};
int main() {
/*定义相关变量*/
int sock_client; //定义客户端套接字
struct sockaddr_in server_addr; //定义存放服务器端地址的结构变量
int addr_len = sizeof(struct sockaddr_in); //地址结构变量长度
/*初始化*/
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
cout << "加载winsock.dll失败!\n";
return 0;
}
/*创建套接字*/
if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl;
WSACleanup();
return 0;
}
/*输入服务器IP地址以及填写服务器地址结构*/
char IP[20];
cout << "请输入服务器地址:";
cin >> IP;
memset((void*)&server_addr, 0, addr_len);//地址结构清零
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
in_addr a;
inet_pton(AF_INET, IP, &a);
server_addr.sin_addr.s_addr = a.S_un.S_addr;//服务器IP地址
/*Connecting Server*/
if (connect(sock_client, (struct sockaddr*)&server_addr, addr_len) != 0)
{
cout << "Connecting Error!!" << WSAGetLastError() << endl;
closesocket(sock_client);
WSACleanup();
return 0;
}
/*输入并发送数据*/
struct Student stud;
cout << "请输入学生的学号、姓名、性别、成绩:\n ";
while (true)
{
cin >> stud.sStID;
if (strcmp(stud.sStID, "end") == 0)
{
cout << "输出结束。" << endl;
break;
}
cin >> stud.sName >> stud.sex >> stud.examination;
/*将结构体中的整型数据字段的值由主机字节顺序的转换为网络字节顺序*/
stud.examination = htonl(stud.examination);
if (send(sock_client, (char*)&stud, sizeof(struct Student), 0) <= 0)
{
cout << "信息发送失败!错误代码:" << WSAGetLastError() << endl;
break;
}
}
/*结束处理*/
closesocket(sock_client);//
WSACleanup();//
return 0;
}
以上代码实现效果客户端只要不输入end,即可一直与服务端通信