最近网络实验课做了好几个实验,我来慢慢分享给大家,首先是做一个socket套接字编程,实现一个C/S模型的简单通信程序。其实是两个程序,一个client端,一个server端。需要从客户端发送字符,然后显示在服务端。这个还是比较简单的。
sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);基于TCP的socket编程是采用的流式套接字。
我这次创建的是TCP的socket。TCP和UDP当然是有区别的,协议方面的事自己去google吧。我就说说在这两种方式下socket编程有哪些区别吧:
服务器端程序设计步骤:
1. 加载套接字库(WSAStartup),创建套接字(socket)。
2. 将套接字绑定IP地址和一个端口(bind)。
3. 将套接字设为监听模式,准备接收客户请求(listen)。
4. 等待客户请求到来。当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。
5. 用返回的套接字和客户端进行通信(send/recv)。
6. 返回,等待另一个客户请求。
7. 关闭套接字(closesocket),关闭加载的套接字库(WSACleanup)。
客户端程序设计步骤:
1. 加载套接字库(WSAStartup),创建套接字(socket)。
2. 向服务器发出连接请求(connect)。
3. 和服务器端进行通信(send/recv)。
4. 关闭套接字(closesocket),关闭加载的套接字库(WSACleanup)。
服务器端程序设计步骤:
1. 加载套接字库(WSAStartup),创建套接字(socket)。
2. 将套接字绑定IP地址和一个端口(bind)。
3. 等待接收数据(recvfrom)。
4. 关闭套接字(closesocket),关闭加载的套接字库(WSACleanup)。
客户端程序设计步骤:
1. 加载套接字库(WSAStartup),创建套接字(socket)。
2. 向服务器发送数据(sendto)。
3. 关闭套接字(closesocket),关闭加载的套接字库(WSACleanup)。
- Server.cpp
- #pragma comment (lib, "ws2_32.lib")
- #include <winsock2.h>
- #include <iostream.h>
- #include <stdlib.h>
- #include <stdio.h>
- #define VERSION_LOW 2
- #define VERSION_HIGH 0
- #define PORT 7777
- #define TEXT_LENGTH 1024
- #define REQUEST_LINE 4
- void main(void)
- {
- //1、加载socket库,版本为2.0
- WORD wVersionRequested; //版本
- WSADATA wsaData;
- int err;
- wVersionRequested = MAKEWORD(VERSION_LOW, VERSION_HIGH);
- err = WSAStartup(wVersionRequested, &wsaData);
- if (err != 0)
- {
- cout << "Socket2.0 Loading Error, Exit!" << endl;
- return;
- }
- //验证版本是否相符
- if (LOBYTE(wsaData.wVersion) != VERSION_LOW || HIBYTE(wsaData.wVersion) != VERSION_HIGH)
- {
- WSACleanup();
- return;
- }
- //2、创建套接字
- SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); //SOCK_STREAM使用的是TCP协议
- if (sockSrv == INVALID_SOCKET)
- {
- cout << "Socket Creating Error, Exit!" << endl;
- WSACleanup();
- return;
- }
- //3、绑定IP地址和端口
- SOCKADDR_IN addrSrv;
- memset(&addrSrv, 0, sizeof(addrSrv));
- addrSrv.sin_family = AF_INET;
- //绑定本地,inet_addr函数把IP转成in_addr结构
- addrSrv.sin_addr.s_addr = INADDR_ANY;
- //端口号必须和客户发往的端口号一致
- addrSrv.sin_port = htons(PORT); //htons函数把整形数转成网络字节序,大端数
- bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
- //4、监听端口,连接请求队列为REQUEST_LINE
- if (listen(sockSrv, REQUEST_LINE) == SOCKET_ERROR)
- {
- closesocket(sockSrv);
- WSACleanup();
- return;
- }
- else
- {
- cout << "listening port succeed!" << endl;
- }
- //5、循环accept客户端来的信息
- SOCKADDR_IN addrCli;
- int len = sizeof(addrCli);
- char sendBuf[TEXT_LENGTH];
- char recvBuf[TEXT_LENGTH];
- SOCKET sockCom = accept(sockSrv, (SOCKADDR *)&addrCli, &len);
- if (sockCom < 0)
- {
- cout << "Communication socket error, exit!" << endl;
- WSACleanup();
- return;
- }
- else
- {
- cout << "Accepted client socket successd!" << endl;
- cout << "The current connect user is from "
- << inet_ntoa(addrCli.sin_addr) << " "
- << htons(addrCli.sin_port) << endl;
- sprintf(sendBuf, "Welcome %s to here!\nYou can type words to me now!\n",
- inet_ntoa(addrCli.sin_addr));
- send(sockCom, sendBuf, TEXT_LENGTH, 0);
- }
- while (1)
- {
- recv(sockCom, recvBuf, TEXT_LENGTH, 0);
- printf("%s\n", recvBuf);
- }
- if (!closesocket(sockCom))
- {
- WSAGetLastError();
- return;
- }
- if (!closesocket(sockSrv))
- {
- WSAGetLastError();
- return;
- }
- if (!WSACleanup())
- {
- WSAGetLastError();
- return;
- }
- }
- Client.cpp
- #include <stdlib.h>
- #include <winsock2.h>
- #include <iostream.h>
- #include <stdio.h>
- #define VERSION_LOW 2
- #define VERSION_HIGH 0
- #define SRV_IP_ADDR "127.0.0.1"
- #define PORT 7777
- #define TEXT_LENGTH 1024
- #pragma comment (lib, "ws2_32.lib")
- //void main(int argc, char **argv)
- void main(void)
- {
- //1、加载socket库,版本为2.0
- WORD wVersionRequested; //版本
- WSADATA wsaData;
- int err;
- wVersionRequested = MAKEWORD(VERSION_LOW, VERSION_HIGH);
- err = WSAStartup(wVersionRequested, &wsaData);
- if (err != 0)
- {
- cout << "Socket2.0 Loading Error, Exit!" << endl;
- return;
- }
- //验证版本是否相符
- if (LOBYTE(wsaData.wVersion) != VERSION_LOW || HIBYTE(wsaData.wVersion) != VERSION_HIGH)
- {
- WSACleanup();
- return;
- }
- //2、创建套接字
- SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0); //SOCK_STREAM使用的是TCP协议
- if (sockCli == INVALID_SOCKET)
- {
- cout << "Socket Creating Error, Exit!" << endl;
- WSACleanup();
- return;
- }
- // char server_IP[TEXT_LENGTH];
- /*
- if (argc < 2)
- {
- printf("Please enter the server's IP!\n");
- return;
- }
- strncpy(server_IP, argv[1], 16);
- */
- // strcpy(server_IP, "192.168.1.100");
- //3、设置socket的IP地址和端口
- SOCKADDR_IN addrSrv;
- memset(&addrSrv, 0, sizeof(addrSrv));
- addrSrv.sin_family = AF_INET;
- //绑定本地,inet_addr函数把IP转成in_addr结构
- addrSrv.sin_addr.s_addr = inet_addr(SRV_IP_ADDR);
- addrSrv.sin_port = htons(PORT); //htons函数把整形数转成网络字节序,大端数
- char sendBuf[TEXT_LENGTH];
- char recvBuf[TEXT_LENGTH];
- if (connect(sockCli, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR)) != 0)
- {
- closesocket(sockCli);
- WSACleanup();
- return;
- }
- else
- {
- cout << "Connecting server succeed!" << endl;
- recv(sockCli, recvBuf, TEXT_LENGTH, 0);
- printf("%s\n", recvBuf);
- }
- printf("Please input the message you want send to server:\n");
- while (1)
- {
- //scanf("%s", sendBuf);
- gets(sendBuf);
- send(sockCli, sendBuf, TEXT_LENGTH, 0);
- }
- if (!closesocket(sockCli))
- {
- WSAGetLastError();
- return;
- }
- if (!WSACleanup())
- {
- WSAGetLastError();
- return;
- }
- }