本文就是在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. MYSQL5.7实时同步数据到TiDB

    操作系统:CentOS7 mysql版本:5.7 TiDB版本:2.0.0 同步方法:使用TiDB提供的工具集进行同步 说明: 单机mysql同步时,可以直接使用binlog同步, 但mysql集群进 ...

  2. ElasicSearch(4) 与jest结合

    https://spring.io/projects/spring-data-elasticsearch https://docs.spring.io/spring-data/elasticsearc ...

  3. EF 6.x实现dynamic动态查询

    利用SqlQuery实现动态查询 public static IEnumerable<dynamic> SqlQueryDynamic(this DbContext db, string ...

  4. 记一个jquery 无缝轮播的制作方法

    接触前端也很久了,今天才发现,要做好一个轮播,其实有很多东西需要考虑进去,否则做出来的轮播效果并不好,下面我就来做一个轮播,是依赖jquery来写的 1.要做轮播,首先需要的是HTML的内容,css的 ...

  5. Java&Android TimeUtil ~ A Good Util!

    时间工具类 import android.text.TextUtils; import android.util.Log; import java.security.MessageDigest; im ...

  6. 550 5.7.1 Client does not have permissions to send as this sender

    收发邮件时出现以上这种情况,系统提示550 5.7.1 Client does not have permissions to send as this sender,这是什么原因赞成的呢? 活动目录 ...

  7. jQuery自定义alert,confirm方法及样式

    学过JavaScript的都知道,alert().confirm()都是window对象特有的方法,而这两个方法我们平时使用的频率也很高,但是比较扎心的就是他自带的样式太... 因此,我整理了一个比较 ...

  8. 分布式版本控制系统Git的安装和使用

    作业要求来自https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2097 GitHub远程仓库的地址:https://github.com/ ...

  9. A除以B

    1017 A除以B (20)(20 分) 本题要求计算A/B,其中A是不超过1000位的正整数,B是1位正整数.你需要输出商数Q和余数R,使得A = B * Q + R成立. 输入格式: 输入在1行中 ...

  10. VS2017安装步骤详解

    原文地址:https://www.ithome.com/html/win10/297093.htm 微软最近发布了正式版Visual Studio 2017并公开了其下载方式,不过由于VS2017采用 ...