【发布时间】:2017-10-24 15:36:38
【问题描述】:
我必须在客户端中键入两个字符串并将它们与结构一起发送到服务器。然后服务器执行c = a + b 并向客户端发送带有{ a, b, c } 的新闻结构。如果收到的a 或b 是quit,则服务器发送给客户端bye。
客户端接收结构并打印c。如果是bye则关闭连接,否则返回询问a和b的输入并重新开始循环。
客户:
#if defined WIN32
#include <Winsock2.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 30
void ClearWinSock() {
#if defined WIN32
WSACleanup();
#endif
}
//-----------------------------INIZIALIZZAZIONE WSADATA
int main (void) {
#if defined WIN32
WSADATA wsaData;
int iResult = WSAStartup (MAKEWORD (2,2), &wsaData);
if (iResult !=0) {
printf ("error at WSASturtup\n");
return 0;
}
#endif
//--------------------------------CREAZIONE SOCKET
int Csocket;
Csocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Csocket < 0) {
printf ("socket creation failed");
closesocket (Csocket);
ClearWinSock();
return 0;
}
char s_address[BUFSIZE];
printf ("Inserisci l'indirizzo dell'host a cui connetterti\n");
scanf ("%s", s_address);
int port;
printf ("Inserisci la porta a cui connetterti\n");
scanf("%d", &port);
struct sockaddr_in sad;
memset (&sad, 0, sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr(s_address);
sad.sin_port = htons (port);
//------------------------------CONNESSIONE AL SERVER
if (connect(Csocket, (struct sockaddr*) &sad, sizeof(sad)) < 0) {
printf ("failed to connect\n");
closesocket (Csocket);
ClearWinSock();
return 0;
}
//-----------------------------RICEZIONE STRINGA DAL SERVER
char buf[BUFSIZE];
int read = recv (Csocket, buf, BUFSIZE - 1, 0);
if (read <=0) {
printf ("Qualcosa non và!\n");
}
else {
buf[read] = '\0'; //tappo stringa per sicurezza
printf("Server scrive: %s\n", buf);
}
//------------------------------STRUTTURA DI STRINGHE
struct stringab {
char a[30];
char b[30];
char c[70];
} ab;
void* abptr = &ab;
printf ("Inserisci prima stringa\n");
scanf ("%s", ab.a);
printf ("Inserisci seconda stringa\n");
scanf ("%s", ab.b);
if (send(Csocket, (char*)abptr, sizeof(ab), 0) != sizeof(ab)) {
printf("client-send() sent a different number of bytes than expected");
closesocket(Csocket);
ClearWinSock();
system ("pause");
return 0;
}
printf ("\n");
closesocket (Csocket);
system ("pause");
ClearWinSock();
return 0;
}
服务器:
#if defined WIN32
#include <Winsock2.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 30
void ClearWinSock() {
#if defined WIN32
WSACleanup();
#endif
}
int main(void) {
//---------------------------INIZIALIZZAZIONE WSADATA
#if defined WIN32
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf ("Error at WSAStartup");
return 0;
}
#endif
//-------------------------------CREAZIONE SOCKET
int Mysocket;
Mysocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
//Valutare la presenza di errori per assicurarsi che la socket sia valida.
if (Mysocket < 0) {
printf("socket creation failed\n");
return 0;
}
//Assegnazione indirizzo alla socket.
struct sockaddr_in sad;
memset(&sad, 0, sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr ("127.0.0.1");
sad.sin_port = htons (9888);
//------------------------ASSEGNAZIONE PORTA E IP ALLA SOCKET
if (bind(Mysocket, (struct sockaddr*) &sad, sizeof(sad)) < 0) {
printf ("bind() failed\n");
closesocket(Mysocket);
return 0;
}
//---------------------------SETTAGGIO SOCKET ALL'ASCOLTO
int qlen = 10; //numero client che il server può gestire
if (listen (Mysocket, qlen) < 0) {
printf("listen() failed\n");
closesocket(Mysocket);
return 0;
}
struct sockaddr_in cad; // struttura per l'indirizzo del cient
int Csocket; // descrittore socket per il client
int clientlen; // lunghezza indirizzo del client
//------------------------------ACCETTA LA CONNESSIONE
while (1) {
printf("In attesa di un client con cui comunicare...\n");
memset(&cad, 0, sizeof(cad));
clientlen = sizeof(cad); // assegna la dimensione dell'indirizzo del client
if((Csocket = accept(Mysocket, (struct sockaddr*) &cad, &clientlen)) < 0) {
printf ("accept failed\n");
closesocket(Mysocket);
ClearWinSock();
return 0;
}
printf("Connessione stabilita con il client il cui indirizzo e' %s \n\n", inet_ntoa(cad.sin_addr));
//---------------------------------------INVIO STRINGA AL CLIENT
char* inputString = "Connessione avvenuta!";
int stringlen = strlen(inputString);
if (send(Csocket, inputString, stringlen, 0) != stringlen) {
printf("client-send() sent a different number of bytes than expected");
closesocket(Csocket);
ClearWinSock();
system ("pause");
return 0;
}
printf ("\n");
closesocket (Csocket);
system ("pause");
ClearWinSock();
return 0;
}
那么,我是否以这种方式将结构发送到服务器?服务器如何recv() 这个结构并做c = a + b 重新构建和重新发送结构?
【问题讨论】:
-
您在发送时是否遇到任何错误?你收到另一边的完整结构了吗?你能详细说明你遇到的问题吗?请read about how to ask good questions,并学习如何创建Minimal, Complete, and Verifiable Example。您可能还应该阅读 Eric Lippert 的 How to debug small programs。
-
主题(我认为):小心以这种方式通过网络发送结构。如果客户端和服务器是不同的类型,它们的程序由不同的编译器编译等等,可能会出错。在大多数情况下,您至少需要一个打包的结构来避免不同的布局。
-
我启动了代码并且输入了两个字符串。发送端似乎没有错误;但我不知道如何在服务器端接收结构,所以我不知道它是否接收没有问题。
-
还要记住 TCP 是一种流协议。您可以在一次发送中发送 100 个字节,但在另一端可能会收到 5 个 20 字节的消息。你必须循环接收,直到你知道你已经收到了所有东西
-
我解决了这个问题。我可以编辑帖子以使其对其他用户有用吗?