C语言网络通信制作:使用winscok实现网络通信

一,ws2.32.lib链接

winsock.h使用之前需要链接ws2.32.lib,否则会报错。

链接方式:

DEVC++:

点击“工具”,选择“编译选项”

8d861692b4cf43c29670aa03500cc992.png

在“在链接时加入以下参数”中填写“-lws2_32” 

c365af93a787464f881358e45e085558.png

VC: 

在源文件的开头添加以下代码:

#pragma comment(lib, "ws2_32.lib")

 二,基本函数,

 初始化Winsock:
 

WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa) 
               //版本号2.2
 //0为初始化成功

 套接字创建:

SOCKET sk;//定义套接字
struct sockaddr_in sa;//定义ipv4和端口号
sk = socket(AF_INET, SOCK_STREAM, 0)
// 创建套接字,INVALID_SOCKET为创建失败

设置服务器地址:

    sa.sin_family = AF_INET;//地址
    sa.sin_addr.s_addr = INADDR_ANY;//接受来自任何网络接口的连接
    //客户端套接字应该把INADDR_ANY改成inet_addr("服务器ip地址");"127.0.0.1"为连接本机
    sa.sin_port = htons(12345);//创建端口号,服务器与客户端端口号需一致

绑定套接字:

bind(sk, (struct sockaddr *)&sa, sizeof(sa))
//将一个本地地址赋予一个套接字,SOCKET_ERROR为绑定失败

 监听连接 :

listen(sk,1);//SOCKET_ERROR为监听失败

接受连接:

 

SOCKET cs;//cs为客户端套接字
struct sockaddr_in ca;
int len = sizeof(ca);//把ca长度赋给len
cs = accept(sk, (struct sockaddr *)&ca, &len);
//返回INVALID_SOCKET为连接失败

发送数据:

       

char i[3];
send(cs//对应套接字
,i//要发送的字符或字符串(字符串末为最好不填,否则可能接收到的数据会出错)
,3//发送长度
,0//正常发送
);

                    

接收数据:

char i[2];
recv(cs,//对应套接字
i,//接收的字符或字符串
2,//接收长度
0,//正常发送
)

示例代码:

服务器:

#include <stdio.h>
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
//#include <windows.h>
int main() {
    WSADATA wsa;
    SOCKET sk, cs;
    struct sockaddr_in sa,ca;
    int len = sizeof(ca);
    // 初始化Winsock
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
        printf("初始化失败\n");
        exit(0);
    }

    // 创建套接字
    if((sk=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
        printf("套接字创建失败\n");
    }

    // 设置服务器地址
    sa.sin_family=AF_INET;//地址
    sa.sin_addr.s_addr=INADDR_ANY;//接受来自任何网络接口的连接
    sa.sin_port=htons(12345);//创建端口号
    
    // 绑定套接字
    if(bind(sk,(struct sockaddr *)&sa,sizeof(sa))==SOCKET_ERROR){
        printf("绑定失败\n");
        exit(0);
    }
    // 监听连接
    if(listen(sk,1)==SOCKET_ERROR)
	{
        printf("监听失败\n");
        exit(0);
    }
    printf("等待客户端连接...\n");

    // 接受连接
    /*
    if ((cs = accept(sk, (struct sockaddr *)&ca, &len))==INVALID_SOCKET)
    {
        printf("连接失败\n");
        exit(0);
    }
    printf("连接成功\n");
    send(cs,"hello",100,0);//发送数据
    char message[100];
    scanf("%s",message);
    while(message!="-1"){
    	if(send(cs,message,100,0)<0)
		{
			printf("发送失败\n");
		}
        scanf("%s",message);
	}
    send(cs,message,100,0);
    closesocket(cs);
    closesocket(sk);
    WSACleanup();
	getchar();
}

 服务器用于接收字符串并发送给客户端,当接收到“-1”时结束通信;(一个服务器只对应一个客户端)

客户端:

#include <stdio.h>
#include <winsock.h>
#include<windows.h>
#include<bits/stdc++.h>
using namespace std;
int main() {
    WSADATA wsa;
    SOCKET cs;
    struct sockaddr_in sa;
    // 初始化Winsock
    if(WSAStartup(MAKEWORD(2, 2),&wsa)!=0){
        printf("初始化失败\n");
        exit(0);
    }
    // 创建套接字
    if((cs=socket(AF_INET, SOCK_STREAM,0))==INVALID_SOCKET){
        printf("套接字创建失败\n");
        exit(0);
    }
    // 设置服务器地址
    sa.sin_family=AF_INET;//ipv4
    sa.sin_addr.s_addr=inet_addr("127.0.0.1");//服务端ip地址(127.0.0.1为连接本机,请根据自己的服务器ip地址进行修改)
    sa.sin_port=htons(12345);//端口号
    // 连接到服务器
    if(connect(cs,(struct sockaddr *)&sa,sizeof(sa))<0)
    {
        printf("连接失败\n");
        exit(0);
    }
    printf("连接成功\n");
    char i[100];
    int j;
    while(1)
	{
		if(recv(cs,i,100,0)>0){
			if(i=="-1"){
				printf("连接断开");
				break;
			}
			printf("接收:%s\n",i);
		}
	}
    closesocket(cs);
    WSACleanup();
	getchar();
}

客户端用于接收服务器发送的数据并打印; 

线程函数:

上面的代码中一个服务器只对应一个客户端,这样只有当处理完一个客户端时才能处理下一个客户端,使用线程函数CreateThread();可以使服务器同时处理多个客户端;

使用方法:

CreateThread(NULL,
0,//指定线程的堆栈大小,0为默认值
s,//DWORD WINAPI类型的函数,需要自己定义,函数中包含一个LPVOID类型数据,可用SOCKET tc=(SOCKET)cs;把LPVOID数据转化成套接字
(LPVOID)cs,//被(LPVOID)转化成LPVOID类型的套接字
0,
NULL//线程ID,NULL为不返回线程ID线程ID可以保存在HANDLE类中,可以通过线程ID对对应线程进行对应操作
);

示例代码:

 服务器: 

#include <stdio.h>
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
//#include <windows.h>
DWORD WINAPI s(LPVOID cs){
    SOCKET tcs=(SOCKET)cs;
    char i[3];
    i[0]=48;
    i[2]=0;
    for(i[1]=48;i[1]<=58;i[1]++)
	{
		Sleep(1000);
		send(tcs,i,3,0);
	}
	i[0]=-1;
	send(tcs,i,3,0);
    closesocket(tcs);
    return 0;
}
int main() {
    WSADATA wsa;
    SOCKET sk, cs;
    struct sockaddr_in sa, ca;
    int len = sizeof(ca);
    // 初始化Winsock
    if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){
        printf("初始化失败\n");
        exit(0);
    }

    // 创建套接字
    if((sk=socket(AF_INET, SOCK_STREAM,0))==INVALID_SOCKET){
        printf("套接字创建失败\n");
    }

    // 设置服务器地址
    sa.sin_family=AF_INET;//地址
    sa.sin_addr.s_addr=INADDR_ANY;//接受来自任何网络接口的连接
    sa.sin_port=htons(12345);//创建端口号
    
    // 绑定套接字
    if(bind(sk,(struct sockaddr *)&sa,sizeof(sa))==SOCKET_ERROR){
        printf("绑定失败\n");
        exit(0);
    }
    // 监听连接
    if(listen(sk,1)==SOCKET_ERROR)
	{
        printf("监听失败\n");
        exit(0);
    }
    printf("等待客户端连接...\n");
    while(1){
		cs=accept(sk,(struct sockaddr *)&ca,&len);
		CreateThread(NULL,0,s,(LPVOID)cs,0,NULL);//线程函数
	}
    closesocket(cs);
    closesocket(sk);
    WSACleanup();
	getchar();
}

服务器运行时每隔一秒向客户端发送依次从01~09的字符串,可接受并同时处理多个客户端;

 客户端:

#include <stdio.h>
#include <winsock.h>
#include<windows.h>
int main() {
    WSADATA wsa;
    SOCKET cs;
    struct sockaddr_in sa;
    // 初始化Winsock
    if(WSAStartup(MAKEWORD(2, 2),&wsa)!=0){
        printf("初始化失败\n");
        exit(0);
    }
    // 创建套接字
    if((cs=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
        printf("套接字创建失败\n");
        exit(0);
    }
    sa.sin_family=AF_INET;//ipv4
    sa.sin_addr.s_addr=inet_addr("127.0.0.1");//服务端ip地址,"127.0.0.1"为连接本机
    sa.sin_port=htons(12345);//端口号
    // 连接到服务器
    if(connect(cs,(struct sockaddr *)&sa,sizeof(sa))<0){
        printf("连接失败\n");
        exit(0);
    }
    printf("连接成功\n");
    char i[3];
    int j;
    while(1)
	{
		if(recv(cs,i,3,0)>0){
			if(i[0]==-1){
				printf("连接断开");
				break;
			}
			printf("接收:%s\n",i);
		}
	}
    closesocket(cs);
    WSACleanup();
	getchar();
}

客户端用于随时接收服务器发送的数据并打印出来; 

运行结果:

712ee27b32a545828fddb13b5aed7028.png

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值