本文就是在windows下进行socket编程,搭建一个TCP客户端。

  在visual studio下编程,首先在windows下进行初始化(这点在linux下是不需要的):

/*
初始化 Winsock
*/ #include<stdio.h>
#include<winsock2.h> #pragma comment(lib,"ws2_32.lib") int main(int argc, char *argv[])
{
WSADATA wsa; printf("\n初始化中Initialising Winsock...");
if (WSAStartup(MAKEWORD(, ), &wsa) != )//Winsock 启动或初始化winsock库,第一个为加载的版本,第二个为WSADATA结构
//WSAStartup应该与WSACleanup成对使用,WSAStartup的功能是初始化Winsock DLL,WSACleanup是来解除与Socket库的绑定并且释放Socket库所占用的系统资源。
{
printf("Failed. Error Code : %d", WSAGetLastError());
return ;
} printf("初始化成功Initialised."); return ;
}

运行结果:

可以看出winsock的环境已经搭建完成了。

下面就是创建一个套接字:

/*
Create a TCP socket
*/ #include<stdio.h>
#include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s; printf("\n初始化Initialising Winsock...");
if (WSAStartup(MAKEWORD(, ), &wsa) != )
{
printf("失败Failed. Error Code : %d", WSAGetLastError());
return ;
} printf("Initialised.\n"); if ((s = socket(AF_INET, SOCK_STREAM, )) == INVALID_SOCKET)
//函数socket()创建一个套接字并返回一个可用于其他网络命令的套接字描述符。
/*
地址系列:AF_INET(这是IP版本4)
类型:SOCK_STREAM(这意味着面向连接的TCP协议)
协议:0 [或IPPROTO_TCP,IPPROTO_UDP]
*/
{
printf("创建失败Could not create socket : %d", WSAGetLastError());
} printf("成功Socket created.\n"); return ;
}

好的,此时我们已经成功地创建了一个套接字。

下面就是通过bind绑定套接字:

#include<stdio.h>
#include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server; printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(, ), &wsa) != )
{
printf("Failed. Error Code : %d", WSAGetLastError());
return ;
} printf("Initialised.\n"); //Create a socket
if ((s = socket(AF_INET, SOCK_STREAM, )) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
} printf("Socket created.\n"); //配置sockaddr_in 结构体
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(); //Bind
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
} puts("Bind done"); closesocket(s); return ;
}

进行调试编译,结果如下:

现在,绑定完成了,它的时间让套接字监听连接。我们将套接字绑定到特定的IP地址和特定的端口号。通过这样做,我们确保所有到这个端口号的传入数据都被这个应用程序接收。

下面进行listen对端口监听,然后accept接收得到的数据。

/*
Bind socket to port 8888 on localhost
*/ #include<stdio.h>
#include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
int c; printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(, ), &wsa) != )
{
printf("Failed. Error Code : %d", WSAGetLastError());
return ;
} printf("Initialised.\n"); //Create a socket
if ((s = socket(AF_INET, SOCK_STREAM, )) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
} printf("Socket created.\n"); //Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(); //Bind
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
} puts("Bind done"); //Listen to incoming connections
if (listen(s, ) != )
{
printf("listen is error");
} //Accept and incoming connection
puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in);
new_socket = accept(s, (struct sockaddr *)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d", WSAGetLastError());
} puts("Connection accepted"); closesocket(s);
WSACleanup(); return ;
}

此时,一个客户端就搭建完成了,下面通过软件对客户端进行实验验证。

创建一个客户端

创建完成后运行称程序,点击连接按钮,可以看到如下输出

上面我们接受了一个传入的连接,但立即关闭。这不是很有成效。传入连接建立后,可以做很多事情。毕竟连接是为了沟通的目的而建立的。所以让我们用send函数回复客户。

/*
Bind socket to port 8888 on localhost
*/
#include<io.h>
#include<stdio.h>
#include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
int c;
char *message; printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(, ), &wsa) != )
{
printf("Failed. Error Code : %d", WSAGetLastError());
return ;
} printf("Initialised.\n"); //Create a socket
if ((s = socket(AF_INET, SOCK_STREAM, )) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
} printf("Socket created.\n"); //Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(); //Bind
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
} puts("Bind done"); //Listen to incoming connections
listen(s, ); //Accept and incoming connection
puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in);
new_socket = accept(s, (struct sockaddr *)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d", WSAGetLastError());
} puts("Connection accepted"); //Reply to client
message = "Hello Client , I have received your connection. But I have to go now, bye\n";
send(new_socket, message, strlen(message), ); getchar(); closesocket(s);
WSACleanup(); return ;
}

同样运行程序,然后点击连接,可以看到调试软件有如下的反馈输出:

虽然有反馈了但是对客户端发送过来的数据没有recv进行显示处理,這里,将整个程序优化如下:

/*
TCP Echo server example in winsock
Live Server on port 8888
*/
#include<stdio.h>
#include<winsock2.h> #pragma comment(lib, "ws2_32.lib") //Winsock Library int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET master, new_socket, client_socket[], s;
struct sockaddr_in server, address;
int max_clients = , activity, addrlen, i, valread;
char *message = "ECHO Daemon v1.0 \r\n"; //size of our receive buffer, this is string length.
int MAXRECV = ;
//set of socket descriptors
fd_set readfds;
//1 extra for null character, string termination
char *buffer;
buffer = (char*)malloc((MAXRECV + ) * sizeof(char)); for (i = ; i < ; i++)
{
client_socket[i] = ;
} printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(, ), &wsa) != )
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
} printf("Initialised.\n"); //Create a socket
if ((master = socket(AF_INET, SOCK_STREAM, )) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
exit(EXIT_FAILURE);
} printf("Socket created.\n"); //Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(); //Bind
if (bind(master, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
} puts("Bind done"); //Listen to incoming connections
listen(master, ); //Accept and incoming connection
puts("Waiting for incoming connections..."); addrlen = sizeof(struct sockaddr_in); while (TRUE)
{
//clear the socket fd set
FD_ZERO(&readfds); //add master socket to fd set
FD_SET(master, &readfds); //add child sockets to fd set
for (i = ; i < max_clients; i++)
{
s = client_socket[i];
if (s > )
{
FD_SET(s, &readfds);
}
} //wait for an activity on any of the sockets, timeout is NULL , so wait indefinitely
activity = select(, &readfds, NULL, NULL, NULL); if (activity == SOCKET_ERROR)
{
printf("select call failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
} //If something happened on the master socket , then its an incoming connection
if (FD_ISSET(master, &readfds))
{
if ((new_socket = accept(master, (struct sockaddr *)&address, (int *)&addrlen))<)
{
perror("accept");
exit(EXIT_FAILURE);
} //inform user of socket number - used in send and receive commands
printf("New connection , socket fd is %d , ip is : %s , port : %d \n", new_socket, inet_ntoa(address.sin_addr), ntohs(address.sin_port)); //send new connection greeting message
if (send(new_socket, message, strlen(message), ) != strlen(message))
{
perror("send failed");
} puts("Welcome message sent successfully"); //add new socket to array of sockets
for (i = ; i < max_clients; i++)
{
if (client_socket[i] == )
{
client_socket[i] = new_socket;
printf("Adding to list of sockets at index %d \n", i);
break;
}
}
} //else its some IO operation on some other socket :)
for (i = ; i < max_clients; i++)
{
s = client_socket[i];
//if client presend in read sockets
if (FD_ISSET(s, &readfds))
{
//get details of the client
getpeername(s, (struct sockaddr*)&address, (int*)&addrlen); //Check if it was for closing , and also read the incoming message
//recv does not place a null terminator at the end of the string (whilst printf %s assumes there is one).
valread = recv(s, buffer, MAXRECV, ); if (valread == SOCKET_ERROR)
{
int error_code = WSAGetLastError();
if (error_code == WSAECONNRESET)
{
//Somebody disconnected , get his details and print
printf("Host disconnected unexpectedly , ip %s , port %d \n", inet_ntoa(address.sin_addr), ntohs(address.sin_port)); //Close the socket and mark as 0 in list for reuse
closesocket(s);
client_socket[i] = ;
}
else
{
printf("recv failed with error code : %d", error_code);
}
}
if (valread == )
{
//Somebody disconnected , get his details and print
printf("Host disconnected , ip %s , port %d \n", inet_ntoa(address.sin_addr), ntohs(address.sin_port)); //Close the socket and mark as 0 in list for reuse
closesocket(s);
client_socket[i] = ;
} //Echo back the message that came in
else
{
//add null character, if you want to use with printf/puts or other string handling functions
buffer[valread] = '\0';
printf("%s:%d - %s \n", inet_ntoa(address.sin_addr), ntohs(address.sin_port), buffer);
send(s, buffer, valread, );
}
}
}
} closesocket(s);
WSACleanup(); return ;
}

运行,程序,打开仿真软件配置后点击连接,可以看到输入如下

输入数据点击发送后可以看到,输出如下:

至此,一个功能基本完备的服务器已经搭建完成了,但是其实这个服务器还是不完善的,这个将在下片文章中进行说明。

下篇文章:

 

vSocket模型详解及select应用详解

27、通过visual s'tudio 验证 SOCKET编程:搭建一个TCP服务器的更多相关文章

  1. 利用socket编程在ESP32上搭建一个TCP客户端

    通过之前http://www.cnblogs.com/noticeable/p/7636582.html中对socket的编程,已经可以知道如何通过socket编程搭建服务器和客户端了,现在,就在ES ...

  2. Windows下C语言的Socket编程例子(TCP和UDP)

    原文:Windows下C语言的Socket编程例子(TCP和UDP) 刚刚学windows编程,所以想写学习笔记,这是一个简单的Socket程序例子,开发环境是vc6: 首先是TCP server端: ...

  3. 5.1 socket编程、简单并发服务器

    什么是socket? socket可以看成是用户进程与内核网络协议栈的编程接口.是一套api函数. socket不仅可以用于本机的进程间通信,还可以用于网络上不同主机间的进程间通信. 工业上使用的为t ...

  4. 使用socket编程实现一个简单的文件服务器

    使用socket编程实现一个简单的文件服务器.客户端程序实现put功能(将一个文件从本地传到文件服务器)和get功能(从文件服务器取一远程文件存为本地文件).客户端和文件服务器不在同一台机器上. pu ...

  5. 使用Java Socket手撸一个http服务器

    原文连接:使用Java Socket手撸一个http服务器 作为一个java后端,提供http服务可以说是基本技能之一了,但是你真的了解http协议么?你知道知道如何手撸一个http服务器么?tomc ...

  6. Socket编程基础——面向连接TCP

    WinSock是Windows环境下的网络编程接口,它最初是基于Unix环境下的BSD Socket,是一个与网络协议无关的编程接口.WinSock包含两个主要版本,即WinSock1和WinSock ...

  7. C# Socket编程(5)使用TCP Socket

    TCP 协议(Transmission Control Protocol,传输控制协议)是TCP/IP体系中面向连接(connection oriented)的传输层(transport layer) ...

  8. socket编程:客户端与服务器间的连接以及各函数的用法

    在认真的看UNP之前,一直被socket编程说的云里雾里,今天我要让大家从整天上认识socket编程,让我们知道socket编程的整个流程和各个函数的用法.这样:我们在写一些简单的socket编程时就 ...

  9. 《java入门第一季》之Socket编程通信和TCP协议通信图解

    Socket编程通信图解原理: TCP协议通信图解

随机推荐

  1. uva-10245-分治

    题意:数组二维空间内的点,求最近的俩个点的距离. 根据x排序,求左部分的最近距离,右部分最近距离,然后以中点,当前距离为半径,计算所有的点距离. #include <string> #in ...

  2. 《算法导论》——重复元素的随机化快排Optimization For RandomizedQuickSort

    昨天讨论的随机化快排对有重复元素的数组会陷入无限循环.今天带来对其的优化,使其支持重复元素. 只需修改partition函数即可: int partition(int *numArray,int he ...

  3. 直接添加viewController中的view时的注意事项

    直接添加viewController中的view时需要注意一个问题,比如: MyTestViewController *vc = [MyTestViewController new]; [self.v ...

  4. 【Noip模拟 20160929】花坛迷宫

    题目描述 圣玛格丽特学园的一角有一个巨大.如迷宫般的花坛.大约有一个人这么高的大型花坛,做成迷宫的形状,深受中世纪贵族的喜爱.维多利加的小屋就坐落在这迷宫花坛的深处.某一天早晨,久城同学要穿过这巨大的 ...

  5. vagrant 同时设置多个同步目录

    修改Vagrantfile文件 如下所示 config.vm.synced_folder "./", "/var/www/pyxis2", owner: &qu ...

  6. 搭建mxnet-gpu docker的pyhon remote kernel

    起因 最近看mxnet的东西,打算给实验室的机器装一个mxnet的环境,无奈实验室里面机器已经装了tensorflow,运行了好久了,环境比较老.而mxnet可是支持最新的cuda9.1和cudnn7 ...

  7. LENGTH()和CHAR_LENGTH()区别

    LENGTH()返回以字节为单位的字符串的长度.CHAR_LENGTH()返回以字符为单位的字符串的长度.   分别对应于java中的str.getBytes().length和str.length( ...

  8. 配置MQTT服务器

    第一步:下载一个Xshell 链接:https://pan.baidu.com/s/16oDa5aPw3G6RIQSwaV8vqw 提取码:zsb4 打开Xshell 前往MQTT服务器软件下载地址: ...

  9. FortiGate日志中session clash

    1.出现于:FortiGate v5.0和v5.2 2.出现原因 Session clash messages appear in the logs when a new session is cre ...

  10. c#: 简单的日志管理类(TextWriterTraceListener)

    以c#实现轻量级的日志管理,着实简单,置一静态类记之: /// <summary> /// 日志管理 /// </summary> public static class Lo ...