本文就是在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. 一步步实现:springbean的生命周期测试代码

    转载. https://blog.csdn.net/baidu_37107022/article/details/76552052 1. 创建实体SpringBean public class Spr ...

  2. grep -A -B -C 显示抓取的前后几行参数

    我经常用grep找东西,比如用户名和密码.大部分站点和用户名和密码都是在一样的,方便grep查找.有时,为了文本好看,我会放在多行.比如 wikipedia多个语言版本上有多个账号,就放在wikipe ...

  3. 异步请求Ajax(取得json数据)

    异步请求Ajax 没有学习Ajax之前请求数据的时候都是整个页面全部刷新了一次,也就是每次请求都会重新请求所有的资源.但是在很多时候不需要页面全部刷新,仅仅是需要页面的局部数据刷新即可,此时需要发送异 ...

  4. Java Day26进程01天

    Java开启多个线程有两种方法,一种继承Thread类,一种实现Runnable接口.具体示例如下: 01继承Thread类 02实现Runnable接口

  5. TCC细读 - 2 核心实现

    TCC,基于业务层面的事物定义,粒度完全由业务自己控制,本质上还是补偿的思路,它把事物运行过程分为try-confirm-cancel阶段,每个阶段逻辑由业务代码控制 业务活动管理器控制业务活动的一致 ...

  6. Apache配置默认主页

    Apache配置默认主页 进入Apache的conf目录 打开httpd.conf文件输入: 在文件末位添加: <Directory "F:/www_php/blog_com/my_b ...

  7. GDI+_入门教程【一】

    GDI For VisualBasic6.0 [一]文件下载:GDI+ For VB6[一] 简单绘图实例演示百度网盘 1 '以下为作者[vIsiaswx]的教程 '(该教程发布的原地址已无法访问,此 ...

  8. MySQL二进制日志(binary log)总结

    本文出处:http://www.cnblogs.com/wy123/p/7182356.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...

  9. Jquery中父,子页面之间元素获取及方法调用

    一.jquery 父.子页面之间页面元素的获取,方法的调用: 1. 父页面获取子页面元素: 格式:$("#iframe的ID").contents().find("#if ...

  10. IDEA 工具从Json自动生成JavaBean

    1.先安装GsonFormat插件:File-->Setting-->Plugins-->GsonFormat-->OK 2.new 一个新的Class空文件,然后 Alt+I ...