windows下的socket网络编程

已经很久没有在windows下编程了,这次因为需要做一个跨平台的网络程序,就先写了个简单的winSocket网路通信的例子,以便以后用到的时候有个参考。

windows下使用winsock编程与linux/unix的区别在于windows下需要先有一个初始化的操作,结束的时候需要一个清理的操作。还有windows下编译的时候需要连接ws32_lib库。

大致过程如下

  • 1、初始化

    /*加载Winsock DLL*/
    WSADATA wsd;
    if (WSAStartup(MAKEWORD(2 , 2) , &wsd) != 0) {
    printf("Winsock 初始化失败!\n");
    return 1;
    }

  • 2、socket相关函数调用

    socket(...)
    bind(...)
    listen(...)
    connect(...)
    accept(...)
    send/sendto
    recv/recvfrom

  • 3、清理
    WSACleanup();

clinet.c 客户端

客户端的流程很简单。

  • 1、先是使用socket函数产生一个打开的socket文件描述符。
  • 2、使用connect函数去连接服务端
  • 3、使用read/recv等读文件函数从服务端接收数据,使用write/send等写文件的函数向服务端发送数据

上面是典型的TCP编程流程,如果是UDP的话不需要connect去连接服务端直接使用sendto函数来发送数据,使用recvfrom接收来自服务器的数据

server.c 服务器端

服务器端的流程比客户端稍微复杂一点

  • 1、调用socket打开一个socket句柄
  • 2、调用bind来绑定socket句柄到一个网口的某个端口
  • 3、调用listen来设置(启用)监听
  • 4、调用accept来等待客户端的连接

上面是典型的TCP编程流程,如果是UDP的,那么不需要3,4这两部,直接使用recvfrom来接收客户端发过来的数据即可。

UDP通信的实现

我这里没有写TCP的,因为都是局域网内,就简单的写了个。
这里是在虚拟机里面测试的截图,代码见最后。

代码如下

这是TCP的,UDP的就不贴了。

#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h> #pragma comment(lib , "ws2_32.lib") #define BUFSIZE 4096 /*缓冲区大小*/ int main_client(int argc , char *argv[])
{
WSADATA wsd;
SOCKET sClient;
char Buffer[BUFSIZE];
int ret;
struct sockaddr_in server;
unsigned short port;
struct hostent *host = NULL; if (argc < ) {
printf("Usage:%s IP Port\n" , argv[]);
return -;
} /*加载Winsock DLL*/
if (WSAStartup(MAKEWORD( , ) , &wsd) != ) {
printf("Winsock 初始化失败!\n");
return ;
} /*创建Socket*/
sClient = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
if (sClient == INVALID_SOCKET) {
printf("socket() 失败: %d\n" , WSAGetLastError());
return ;
}
/*指定服务器地址*/
server.sin_family = AF_INET;
port = atoi(argv[]);
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(argv[]); if (server.sin_addr.s_addr == INADDR_NONE) {
host = gethostbyname(argv[]); //输入的地址可能是域名等
if (host == NULL) {
printf("无法解析服务端地址: %s\n" , argv[]);
return ;
}
CopyMemory(&server.sin_addr ,
host->h_addr_list[] ,
host->h_length);
}
/*与服务器建立连接*/
if (connect(sClient , (struct sockaddr*)&server ,
sizeof(server)) == SOCKET_ERROR) {
printf("connect() 失败: %d\n" , WSAGetLastError());
return ;
} /*发送、接收消息*/ for (;;) {
//从标准输入读取要发送的数据
//gets_s(Buffer,BUFSIZE);
gets(Buffer);
//向服务器发送消息
ret = send(sClient , Buffer , strlen(Buffer) , );
if (ret == ) {
break;
}
else if (ret == SOCKET_ERROR) {
printf("send() 失败: %d\n" , WSAGetLastError());
break;
}
printf("Send %d bytes\n" , ret);
//接收从服务器来的消息
ret = recv(sClient , Buffer , BUFSIZE , );
if (ret == ) {
break;
}
else if (ret == SOCKET_ERROR) {
printf("recv() 失败: %d\n" , WSAGetLastError());
break;
}
Buffer[ret] = '\0';
printf("Recv %d bytes:\n\t%s\n" , ret , Buffer); }
//用完了,关闭socket句柄(文件描述符)
closesocket(sClient);
WSACleanup(); //清理
return ;
}

查看 clinet.c 代码

 #include <winsock2.h>
#include <stdio.h>
#include <stdlib.h> #pragma comment(lib , "ws2_32.lib") #define DEFAULT_BUFFER 4096 /*缓冲区大小*/ /*与客户机通信的线程函数*/
DWORD WINAPI ClientThread(LPVOID lpParam)
{
SOCKET sock = (SOCKET)lpParam;
char Buffer[DEFAULT_BUFFER];
int ret , nLeft , idx;
while () {
/*接收来自客户机的消息*/
ret = recv(sock , Buffer , DEFAULT_BUFFER , );
if (ret == )
break;
else if (ret == SOCKET_ERROR) {
printf("recv() 失败: %d\n" , WSAGetLastError());
break;
}
Buffer[ret] = '\0';
printf("Recv: %s\n" , Buffer); //打印接收到的消息 nLeft = ret;
idx = ;
while (nLeft > ) {
/*向客户机发送回应消息*/
ret = send(sock , &Buffer[idx] , nLeft , );
if (ret == )
break;
else if (ret == SOCKET_ERROR) {
printf("send() 失败: %d\n" , WSAGetLastError());
break;
}
nLeft -= ret;
idx += ret;
}
}
return ;
} int main_server(int argc , char **argv)
{
WSADATA wsd;
HANDLE hThread;
DWORD dwThread;
SOCKET sListen , sClient;
int AddrSize;
unsigned short port;
struct sockaddr_in local , client; if (argc < ) {
printf("Usage:%s Port\n" , argv[]);
return -;
} /*加载Winsock DLL*/
if (WSAStartup(MAKEWORD( , ) , &wsd) != ) {
printf("WinSock 初始化失败!\n");
return ;
} /*创建Socket*/
sListen = socket(AF_INET , SOCK_STREAM , IPPROTO_IP);
if (sListen == SOCKET_ERROR) {
printf("socket() 失败: %d\n" , WSAGetLastError());
return ;
} local.sin_family = AF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);
port = atoi(argv[]); //获取端口值
local.sin_port = htons(port); /*绑定Socket*/
if (bind(sListen ,
(struct sockaddr*)&local ,
sizeof(local)) == SOCKET_ERROR) {
printf("bind() 失败: %d\n" , WSAGetLastError());
return ;
}
/*打开监听*/
listen(sListen , ); /*在端口进行监听,一旦有客户机发起连接请示
就建立与客户机进行通信的线程*/
while () {
AddrSize = sizeof(client);
/*监听是否有连接请求*/
sClient = accept(sListen ,
(struct sockaddr*)&client ,
&AddrSize);
if (sClient == INVALID_SOCKET) {
printf("accept() 失败: %d\n" , WSAGetLastError());
break;
}
printf("接受客户端连接: %s:%d\n" ,
inet_ntoa(client.sin_addr) ,
ntohs(client.sin_port)); //创建一个线程去处理
hThread = CreateThread(NULL , , ClientThread ,
(LPVOID)sClient , , &dwThread); if (hThread == NULL) {
printf("CreateThread() 失败: %d\n" , GetLastError());
break;
}
//处理完后关闭
CloseHandle(hThread);
}
closesocket(sListen);
WSACleanup(); //用完了要清理
return ;
}

查看 server.c 代码

测试代码(main)

 extern int main_client(int , char**);
extern int main_server(int , char**); int main(int c , char** v)
{
if (c == ) {
main_client(c , v);
}
else {
main_server(c , v);
}
return ; }

查看 test 代码

windows下的socket网络编程的更多相关文章

  1. windows下的socket网络编程(入门级)

    windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了,这次因为需要做一个跨平台的网络程序,就先 ...

  2. Cfree clion windows c语言 socket 网络编程

    server.c #include <stdio.h> #include <winsock2.h> #define SERVER_PORT 5208 //侦听端口 int ma ...

  3. winsock教程- windows下的socket编程(c语言实现)

    winsock教程- windows下的socket编程(c语言实现) 使用winsock进行socket 编程     这是一个学习windows下socket编程(c语言)的快速指南.这是因为一下 ...

  4. windows socket网络编程基础知识

    下面介绍网络7层协议在WINDOWS的实现: 7层协议 WIN系统 ________________________________________ 7 应用层 7 应用程序 ____________ ...

  5. windows socket 网络编程

    样例代码就在我的博客中,包含六个UDP和TCP发送接受的cpp文件,一个基于MFC的局域网聊天小工具project,和此小工具的全部执行时库.资源和执行程序.代码的压缩包位置是http://www.b ...

  6. linux下C语言socket网络编程简例

    原创文章,转载请注明转载字样和出处,谢谢! 这里给出在linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到client的连接后,发送数据给client:clie ...

  7. 5.3linux下C语言socket网络编程简例

    原创文章,转载请注明转载字样和出处,谢谢! 这里给出在Linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到客户端的连接后,发送数据给客户端:客户端在接受到数据后 ...

  8. 项目总结——深入浅出socket网络编程

    前言: 为什么会有如题的概念呢,我想对于没有主动听说过socket网络编程的人来说读到题目可能就已经蒙头了,为了很好的让大家进入场景,首先说一下一个需要用到这点东西的业务需求. 首先大家应该明确的是s ...

  9. Socket网络编程详解

    一,socket的起源 socket一词的起源 在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的, 撰写者为Stephen Carr.Steve Crocker和Vi ...

随机推荐

  1. docker网络基础配置

    常用两种方式: 1)映射容器端口到宿主机 2)容器互联机制 --------------------------------------------- 端口映射实现访问容器的用法: docker ru ...

  2. ecshop登录

    邮箱登录 a.找到function login(){} ,增加一个邮箱判断is_mail()  , b.如果通过,增读取出username , c.再通过默认的login功能 1.需要修改文件incl ...

  3. php 下载文件的函数

    通过函数完成下载文件的PHP功能代码 function download($url, $filename) { // 获得文件大小, 防止超过2G的文件, 用sprintf来读 $filesize = ...

  4. 关于Unity动态物体无法向使用使用custom shader和lightmap的物体投射阴影

    最近在做unity shader forge和marmoset的优化,TA那边遇到了一个阴影显示的问题,具体如下:   在Forward Rendering状态下,静态场景使用了是shader for ...

  5. Hibernate与Mybatis的概念区别

    首先简单介绍下两者的概念: Hibernate :Hibernate 是当前最流行的ORM框架,对数据库结构提供了较为完整的封装. Mybatis:Mybatis同样也是非常流行的ORM框架,主要着力 ...

  6. WEBSTORM 打开多个项目的方法

    WebStorm默认情况下一次只能打开一个项目,这点很不爽,其实是可以设置的. 方法: File -> settings -> Directories -> Add Content ...

  7. 注册Com组件..

    开发一些第三方的接口或者功能时..有时会需要接入对方提供Com组件..是一个dll文件.. 这个文件会在你的程序中引用.. 比如一个CMBChina.dll文件..这是招商银行的支付开发时必备的.. ...

  8. idea引用自己的插件

  9. 关于帧中继和ppp的补充笔记

    帧中继: · 两个设备都要启用 帧中继功能, 否则是不能 ping通的 · 两个设备上的接口serial要 no shutdown · · 一定要配置dlci地址(号). 否则就不能起来pvc 可以 ...

  10. iSCSI配置流程

    Windows群集两个节点:分别在SQL01和SQL02设置连接共享磁盘: 此前已经在存储服务器通过StarWind创建了三个虚拟磁盘:Quemon+data+backup:starwind安装请参考 ...