Windows下c利用socket編寫簡易服務(wù)端程序
由于一些原因沒法用需要安裝的TCP/UDP測試工具,又懶得去找綠色版,所以我干脆弄了一個簡單的檢測收發(fā)的c的服務(wù)端程序,僅支持一輪的收發(fā)過程(可自行依據(jù)需求擴展)。
注意:僅支持一輪消息的收發(fā)
注意:這是在windows下的,linux之類的環(huán)境的話會有些不一樣(需要修改部分內(nèi)容)
注意:代碼中大量的注釋是為了更方便調(diào)整,免得還要找一次資料
注意:直接拷貝就能使用,不需要再加什么包或配置(注意代碼中設(shè)置的端口)
注意:只是隨手搞得,也只是一個臨時的工具,代碼不是很精妙
#include <stdio.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main() {
????WSADATA wsaData; //用于填充套接字庫版本的有關(guān)信息
????//加載Winsock 2.2版本
????if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
????????printf("WSAStartup failed");
????????return -1;
????}
????/*
????????int socket(int domain, int type, int protocol);
在參數(shù)表中,domain指定使用何種的地址類型,比較常用的有:
PF_INET, AF_INET: Ipv4網(wǎng)絡(luò)協(xié)議;
PF_INET6, AF_INET6: Ipv6網(wǎng)絡(luò)協(xié)議。
type參數(shù)的作用是設(shè)置通信的協(xié)議類型,可能的取值如下所示:
SOCK_STREAM: 提供面向連接的穩(wěn)定數(shù)據(jù)傳輸,即TCP協(xié)議。
OOB: 在所有數(shù)據(jù)傳送前必須使用connect()來建立連接狀態(tài)。
SOCK_DGRAM: 使用不連續(xù)不可靠的數(shù)據(jù)包連接。
SOCK_SEQPACKET: 提供連續(xù)可靠的數(shù)據(jù)包連接。
SOCK_RAW: 提供原始網(wǎng)絡(luò)協(xié)議存取。
SOCK_RDM: 提供可靠的數(shù)據(jù)包連接。
SOCK_PACKET: 與網(wǎng)絡(luò)驅(qū)動程序直接通信。
參數(shù)protocol用來指定socket所使用的傳輸協(xié)議編號。這一參數(shù)通常不具體設(shè)置,一般設(shè)置為0即可。
????????#define IPPROTO_IP 0? ? ?dummy for IP(IP虛擬機)
????????#define IPPROTO_ICMP 1? ?control message protocol(控制消息協(xié)議)
????????#define IPPROTO_IGMP 2? ?internet group management protocol (internet組管理協(xié)議)
????????#define IPPROTO_GGP 3? ? gateway^2 (deprecated)(網(wǎng)關(guān)^2(已棄用))
????????#define IPPROTO_TCP? 6? ?tcp
????????#define IPPROTO_PUP 12? ?pup
????????#define IPPROTO_UDP 17? ?user datagram protocol(用戶數(shù)據(jù)報協(xié)議)
????????#define IPPROTO_IDP 22? ?xns idp
????????#define IPPROTO_ND 77? ? UNOFFICIAL net disk proto(非官方網(wǎng)絡(luò)磁盤協(xié)議)
????????#define IPPROTO_RAW 255? raw IP packet(原始的IP包)
????????#define IPPROTO_MAX 256
????*/
????SOCKET sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);// 創(chuàng)建套接字
????if (sockfd == INVALID_SOCKET) {
????????perror("socket");
????????return -1;
????} // 創(chuàng)建失敗的錯誤處理?
????printf("socket..............\n"); // 成功則打印“socket。。。?!?
????struct sockaddr_in myaddr; // 創(chuàng)建“我的地址”結(jié)構(gòu)體?
????memset(&myaddr, 0, sizeof(myaddr)); // 對內(nèi)存清零(保險起見)?
????myaddr.sin_family = AF_INET; // 選擇IPV4地址類型?
????myaddr.sin_port = htons(7000); // 選擇端口號?
????myaddr.sin_addr.s_addr = htonl(2130706433); // 選擇IP地址?
????if (bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr)) == SOCKET_ERROR) { // 綁定套接字?
????????perror("bind");
????????return -1;
????}
????printf("bind..........\n");
????if (listen(sockfd, 8) == SOCKET_ERROR) { // 調(diào)用listen對指定端口進行監(jiān)聽?
????????perror("listen");
????????return -1;
????}
????printf("listen............\n");
????//循環(huán)接收數(shù)據(jù)
????SOCKET sClient;
????struct sockaddr_in remoteAddr;
????int nAddrlen = sizeof(remoteAddr);
????printf("waiting link...\n");
????sClient = accept(sockfd, (SOCKADDR*)& remoteAddr, &nAddrlen);
????while (1) {
????????????if (sClient == INVALID_SOCKET) {
????????????????printf("accept error !");
????????????????break;
????????????}
????????char str[INET_ADDRSTRLEN];
????????inet_ntop(AF_INET, &remoteAddr.sin_addr, str, sizeof(str));
????????printf("receive a link:%s \n", str);
????????//接收數(shù)據(jù)
????????/*
????????????函數(shù)原型:int recv( SOCKET s, char *buf, int len, int flags )
????????????功能:不論是客戶還是服務(wù)器應(yīng)用程序都用recv函數(shù)從TCP連接的另一端接收數(shù)據(jù)。
????????????參數(shù)一:指定接收端套接字描述符;
????????????參數(shù)二:指明一個緩沖區(qū),該緩沖區(qū)用來存放recv函數(shù)接收到的數(shù)據(jù);
????????????參數(shù)三:指明buf的長度;
????????????參數(shù)四 :一般置為0。
????????*/
????????char revData[256];
????????int ret = recv(sClient, revData, 255, 0);
????????if (ret <= 0) {
????????????printf("%d \n", ret);
????????????perror("recv");
????????????printf("%d \n", WSAGetLastError());
????????????// 10054錯誤表示連接被遠程主機重置
????????????// 所以為了c-s之間能穩(wěn)定交互,要保證交互結(jié)束前不能結(jié)束程序的運行
????????????break;
????????}
????????revData[ret] = 0x00;
????????printf("got data:\n");
????????printf("%s", revData);
????????//發(fā)送數(shù)據(jù)
????????printf("\nsend message to Client \n");
????????const char* sendData = "hello! client \n";
????????send(sClient, sendData, strlen(sendData), 0);
????????break;
????}
????Sleep(10000);
????closesocket(sClient);
????closesocket(sockfd);
????WSACleanup();
????printf("over \n");
????system("pause");
????return 0;
}
