【C语言随笔2】GCC编译环境下Socket编程简单实践

Socket原理-TCP三次握手代码参考:
https://blog.csdn.net/panker2008/article/details/46502783

Server(服务端)

#include <winsock2.h>
#include <stdio.h>
#include <time.h>

int main()
{     
       // 数据缓冲变量准备 
       char sendBuf[100]; //发送信息
       int turn = 0; //数据是否发送完毕,1表示完毕,0表示未发送完毕
       char receiveBuf[100];//接收
       int stime, etime, timeout; //超时计时器

       // 初始化,初始化后进去监听状态
       // 创建套接字,socket前的一些检查工作,包括服务的启动
       WORD myVersionRequest;
       WSADATA wsaData;
       myVersionRequest = MAKEWORD(1,1);
       int err;
       err = WSAStartup(myVersionRequest,&wsaData);
       if (!err)
       {
              printf("Socket has openned...\n");            
       }
       else
       {
              //进一步绑定套接字
              printf("Socket doesn't open...");
              return 0;
       }
       SOCKET serSocket = socket(AF_INET,SOCK_STREAM,0);//创建了可识别套接字
       //需要绑定的参数,主要是本地的socket的一些信息。
       SOCKADDR_IN addr;
       addr.sin_family = AF_INET;
       addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//ip地址
       addr.sin_port = htons(6000);//绑定端口
 
       bind(serSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//绑定完成
       listen(serSocket,5);//监听,其中第二个参数代表能够接收的最多的连接数
 
       SOCKADDR_IN clientsocket;
       int len = sizeof(SOCKADDR);
       
       // 连接对象
       SOCKET serConn;
       //第二次握手,通过accept来接受对方的套接字的信息
       serConn = accept(serSocket,(SOCKADDR*)&clientsocket,&len);//如果这里不是accept而是conection的话,就会不断的监听
       sprintf(sendBuf,"welcome %s to Sunking's Service!",inet_ntoa(clientsocket.sin_addr));//找对对应的IP并且将这行字打印到那里
       send(serConn,sendBuf,strlen(sendBuf)+1,0);

       // 计时器启动
       stime = time(0);
       timeout  = 0;

       // 交互模块
       while(1){
              // 10s超时后,执行和新用户的第二次握手,通过accept来接受对方的套接字的信息
              if(timeout > 10){
                     printf("\nwait client to connect...");
                     printf("\n");
                     serConn = accept(serSocket,(SOCKADDR*)&clientsocket,&len);//如果这里不是accept而是conection的话,就会不断的监听
                     sprintf(sendBuf,"welcome %s to Sunking's Service!",inet_ntoa(clientsocket.sin_addr));//找对对应的IP并且将这行字打印到那里
                     send(serConn,sendBuf,strlen(sendBuf)+1,0);
              }

              // 接受第三次握手发来的消息
              memset(receiveBuf, '\0', strlen(receiveBuf)+1);
              recv(serConn,receiveBuf,strlen(receiveBuf)+1,0);
              if (strlen(receiveBuf) == 0 && turn)
              {      
                     turn = 0;

                     // 成功接收完客户端发来的消息
                     sprintf(sendBuf, "receive successfully!\n");
                     send(serConn,sendBuf,strlen(sendBuf)+1,0);

                     printf("\nFinish to receive client's data, wait...\n");
              }else if(strlen(receiveBuf) != 0 && !turn){
                     stime = time(0); // 若开始收到来自client的消息,刷新开始时间
                     turn = 1;
              }// 否则什么也不做
              printf("%s",receiveBuf);

              // 计时
              etime = time(0);
              timeout = etime - stime;
       }
       
       closesocket(serConn);//关闭
       WSACleanup();//释放资源的操作

       return 0;
}

Client(客户端)

#include <winsock2.h>              
#include <stdio.h>

int main()
{
	//SOCKET前的一些检查,检查协议库的版本,为了避免别的版本的socket,并且通过
	//WSAStartup启动对应的版本,WSAStartup的参数一个是版本信息,一个是一些详细的细节,注意高低位
	//WSAStartup与WSACleanup对应
	int err;
	WORD versionRequired;
	WSADATA wsaData;
	versionRequired = MAKEWORD(1,1);     
	err = WSAStartup(versionRequired,&wsaData);//协议库的版本信息
 
	//通过WSACleanup的返回值来确定socket协议是否启动
	if (!err)
	{
		printf("Client socket has openned...\n");
	}
	else
	{
		printf("Client socket is failed to open...\n");
		return 0;//结束
	}
	//创建socket这个关键词,这里想一下那个图形中的socket抽象层
	//注意socket这个函数,他三个参数定义了socket的所处的系统,socket的类型,以及一些其他信息
	SOCKET clientSocket = socket(AF_INET,SOCK_STREAM,0);
 
	//socket编程中,它定义了一个结构体SOCKADDR_IN来存计算机的一些信息,像socket的系统,
	//端口号,ip地址等信息,这里存储的是服务器端的计算机的信息
	SOCKADDR_IN clientsock_in;
	clientsock_in.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");// 127.0.0.1本地自回路
	clientsock_in.sin_family = AF_INET;
	clientsock_in.sin_port = htons(6000);
 
	//前期定义了套接字,定义了服务器端的计算机的一些信息存储在clientsock_in中,
	//准备工作完成后,然后开始将这个套接字链接到远程的计算机
	//也就是**第一次握手**
 
	connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//开始连接
 
 	// 接受第二次握手发来的消息
	char receiveBuf[100];
 
	//解释socket里面的内容
	recv(clientSocket,receiveBuf,101,0);
	printf("%s\n",receiveBuf);
 
	//发送socket数据,第三次握手
	char sendBuf[100];
    sprintf(sendBuf,"\nClient successfully connect!\n");
	send(clientSocket,sendBuf,strlen(sendBuf)+1,0); 

	// 用户向服务器发送信息
	char quit[100];
	while(1){
		printf(">> Send data?(q or Q to quit): ");

		// 用户请求
		gets(quit);

		// 用户结束访问
		if (quit[0] == 'q' || quit[0] == 'Q' && quit[1] == '\0'){
			break;
		}

		// 用户输入数据
		printf("\n>> Input your data: ");
		gets(sendBuf);
		send(clientSocket,sendBuf,strlen(sendBuf)+1,0);

		// 数据接收成功判断
		while(1){
			memset(receiveBuf, '\0', strlen(receiveBuf)+1);
			recv(clientSocket,receiveBuf,strlen(receiveBuf)+1,0);
			if (strlen(receiveBuf) == 0)
			{
				break;
			}
			printf("%s", receiveBuf);
		}

	}
 
	//关闭套接字
	closesocket(clientSocket);
	//关闭服务
	WSACleanup();
	return 0;
}
 

运行方式(本人是win10的cmd下执行)

执行过程:

  1. client.exe:
    gcc -o client client.c MinGW绝对路径\lib\libws2_32.a MinGW绝对路径\lib\libwsock32.a
  2. server.exe:
    gcc -o server server.c MinGW绝对路径\lib\libws2_32.a MinGW绝对路径\lib\libwsock32.a
  3. 先运行server,server进入监听状态,再运行client,三次握手完成TCP建立;
  4. 按照提示从客户端向服务器端传输字符串(客户端用户10s不传输,会默认超时,若客户端关闭可重新打开新的客户端建立连接,否则正常执行

结果:
socket-result

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值