TCP实现Linux与Windows之间数据传输

来源:互联网 发布:什么人适合学编程 编辑:程序博客网 时间:2024/05/27 20:51

实验要求:用两台计算机,一台是服务器另一台是客户端,运行结果要求在客户端把键入的字符串发送给服务器,服务器显示收到的字符串,并将字符串发回给客户端,客户端显示服务器发回的字符串。要求客户端能够多次发送字符串,服务器能够不断的接收并显示和发送。

Linux服务器:

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <signal.h>
extern void sig_proccess(int signo);
#define PORT 8888 /*侦听端口地址*/
#define BACKLOG 2 /*侦听队列长度*/
int main(int argc, char*argv[])
{
int ss,sc; /*ss为服务器的socket描述符,sc为客户端的socket描述符*/
struct sockaddr_in server_addr; /*服务器地址结构*/
struct sockaddr_in client_addr;/*客户端地址结构*/
int err; /*错误值*/
pid_t pid; /*分叉的进行id*/

signal(SIGINT, sig_proccess);/*挂接SIGINT信号,处理函数为sig_process()*/
signal(SIGPIPE, sig_proccess);/*挂接SIGPIPE信号,处理函数为sig_pipe()*/

ss = socket(AF_INET, SOCK_STREAM, 0);/*建立一个流式套接字*/
if(ss < 0){ /*出错*/
printf("socket error\n");
return -1;
}

/*设置服务器地址*/
bzero(&server_addr, sizeof(server_addr));/*清零*/
server_addr.sin_family = AF_INET;/*协议族*/
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);/*本地地址*/
server_addr.sin_port = htons(PORT);/*服务器端口*/
/*绑定地址结构到套接字描述符*/
err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(err < 0){ /*绑定出错*/
printf("bind error\n");
return -1;
}
err = listen(ss, BACKLOG);/*设置侦听队列长度*/
if(err < 0){ /*出错*/
printf("listen error\n");
return -1;
}
/*主循环过程*/
for(;;) {
int addrlen = sizeof(struct sockaddr);
/*接收客户端连接*/
sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen);
if(sc < 0){ /*客户端连接出错*/
continue; /*结束本次循环*/
}

/*建立一个新的进程处理到来的连接*/
pid = fork(); /*分叉进程*/
if( pid == 0 ){/*子进程中*/
close(ss); /*在子进程中关闭服务器的侦听*/
process_conn_server(sc);/*处理连接*/
}else{
close(sc); /*在父进程中关闭客户端的连接*/
}
}
}

*******************处理函数***********************

#include <stdio.h>
#include <string.h>
#include <unistd.h>
/*服务器对客户端的处理*/
void process_conn_server(int s)
{
ssize_t size = 0;
char buffer[1024];/*数据的缓冲区*/

for(;;){ /*循环处理过程*/
size = recv(s, buffer, 1024,0);
/*从套接字中读取数据放到缓冲区buffer中*/
if(size == 0){/*没有数据*/
return;
}
write(1,buffer,size);/*写到标准输出*/
printf("\n");
//sprintf(buffer, "%d bytes altogether\n", size);/*构建响应字符,为接收到客户端字节的数量*/
sprintf(buffer,"%s this is server return\n",buffer);
send(s, buffer, strlen(buffer)+1,0);/*发给客户端*/
memset(&buffer,0,sizeof(buffer)); /*清空缓冲区*/
}
}

Windows客户端:

// TCPClient.cpp : 定义控制台应用程序的入口点。
//




// TcpClient.cpp : 客户端程序
//
#include "stdafx.h"
#include <WinSock2.h> 
#include <string>
#include <stdlib.h>
#include <iostream> 
using namespace std;
#pragma comment(lib,"WS2_32.Lib") 
#define BUF_SIZE 64 // 缓冲区大小 


int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsd; // 用于初始化Windows Socket 
SOCKET sHost; // 与服务器进行通信的套接字 
SOCKADDR_IN servAddr; // 服务器地址 
char buf[BUF_SIZE]; // 用于接受数据缓冲区 
int retVal; 
// 初始化Windows Socket
if(WSAStartup(MAKEWORD(2,2),&wsd) != 0) 

printf("WSAStartup failed !\n"); 
return 1; 
}
// 创建套接字 
sHost = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
if(INVALID_SOCKET == sHost) 

printf("socket failed !\n"); 
WSACleanup(); 
return -1; 

// 设置服务器地址 
servAddr.sin_family = AF_INET; 
servAddr.sin_addr.S_un.S_addr = inet_addr("192.168.19.88"); // 用户需要根据实际情况修改
servAddr.sin_port = htons(8888); // 在实际应用中,建议将服务器的IP地址和端口号保存在配置文件中
int sServerAddlen = sizeof(servAddr);
// 循环连接服务器
while(true)
{
retVal = connect(sHost,(LPSOCKADDR)&servAddr,sizeof(servAddr)); 
if(INVALID_SOCKET == sHost) 

int err = WSAGetLastError();
if(err == WSAEWOULDBLOCK) // 无法立即完成非阻塞套接字上的操作
{
Sleep(500);
printf("continue !\n"); 
continue;
}
else
{
printf("accept failed !\n"); 
closesocket(sHost); 
WSACleanup(); 
return -1; 
}

printf("accept OK!\n"); 
Sleep(500);
break;

// 循环向服务器发送字符串,并显示反馈信息。
// 发送quit将使服务器程序退出,同时客户端程序自身也将退出
while(true)
{
// 向服务器发送数据 
printf("Please input a string to send: ");
// 接收输入的数据
std::string str;
std::getline(std::cin, str);
// 将用户输入的数据复制到buf中
ZeroMemory(buf,BUF_SIZE); 
strcpy_s(buf,str.c_str()); 
// 向服务器发送数据
retVal = send(sHost,buf,strlen(buf),0); 
//清空缓冲区
memset(&buf,0,sizeof(buf));
if(SOCKET_ERROR == retVal) 

printf("send failed !\n"); 
closesocket(sHost); 
WSACleanup(); 
return -1; 



// 接收服务器回传的数据 
retVal = recv(sHost,buf,sizeof(buf)+1,0); 
printf_s("Recv From Server: %s\n",buf); 


// 如果收到quit,则退出
//if(strcmp(buf, "quit") == 0)
//{
//printf("quit!\n");
//break;
//}
}
// 释放资源 
closesocket(sHost); 
WSACleanup(); 
// 暂停,按任意键继续
system("pause");
return 0; 
}